SemaFixItUtils.cpp revision 226586
1226586Sdim//===--- SemaFixItUtils.cpp - Sema FixIts ---------------------------------===// 2226586Sdim// 3226586Sdim// The LLVM Compiler Infrastructure 4226586Sdim// 5226586Sdim// This file is distributed under the University of Illinois Open Source 6226586Sdim// License. See LICENSE.TXT for details. 7226586Sdim// 8226586Sdim//===----------------------------------------------------------------------===// 9226586Sdim// 10226586Sdim// This file defines helper classes for generation of Sema FixItHints. 11226586Sdim// 12226586Sdim//===----------------------------------------------------------------------===// 13226586Sdim 14226586Sdim#include "clang/AST/ExprCXX.h" 15226586Sdim#include "clang/AST/ExprObjC.h" 16226586Sdim#include "clang/Lex/Preprocessor.h" 17226586Sdim#include "clang/Sema/Sema.h" 18226586Sdim#include "clang/Sema/SemaFixItUtils.h" 19226586Sdim 20226586Sdimusing namespace clang; 21226586Sdim 22226586Sdimbool ConversionFixItGenerator::compareTypesSimple(CanQualType From, 23226586Sdim CanQualType To, 24226586Sdim Sema &S, 25226586Sdim SourceLocation Loc, 26226586Sdim ExprValueKind FromVK) { 27226586Sdim if (!To.isAtLeastAsQualifiedAs(From)) 28226586Sdim return false; 29226586Sdim 30226586Sdim From = From.getNonReferenceType(); 31226586Sdim To = To.getNonReferenceType(); 32226586Sdim 33226586Sdim // If both are pointer types, work with the pointee types. 34226586Sdim if (isa<PointerType>(From) && isa<PointerType>(To)) { 35226586Sdim From = S.Context.getCanonicalType( 36226586Sdim (cast<PointerType>(From))->getPointeeType()); 37226586Sdim To = S.Context.getCanonicalType( 38226586Sdim (cast<PointerType>(To))->getPointeeType()); 39226586Sdim } 40226586Sdim 41226586Sdim const CanQualType FromUnq = From.getUnqualifiedType(); 42226586Sdim const CanQualType ToUnq = To.getUnqualifiedType(); 43226586Sdim 44226586Sdim if ((FromUnq == ToUnq || (S.IsDerivedFrom(FromUnq, ToUnq)) ) && 45226586Sdim To.isAtLeastAsQualifiedAs(From)) 46226586Sdim return true; 47226586Sdim return false; 48226586Sdim} 49226586Sdim 50226586Sdimbool ConversionFixItGenerator::tryToFixConversion(const Expr *FullExpr, 51226586Sdim const QualType FromTy, 52226586Sdim const QualType ToTy, 53226586Sdim Sema &S) { 54226586Sdim if (!FullExpr) 55226586Sdim return false; 56226586Sdim 57226586Sdim const CanQualType FromQTy = S.Context.getCanonicalType(FromTy); 58226586Sdim const CanQualType ToQTy = S.Context.getCanonicalType(ToTy); 59226586Sdim const SourceLocation Begin = FullExpr->getSourceRange().getBegin(); 60226586Sdim const SourceLocation End = S.PP.getLocForEndOfToken(FullExpr->getSourceRange() 61226586Sdim .getEnd()); 62226586Sdim 63226586Sdim // Strip the implicit casts - those are implied by the compiler, not the 64226586Sdim // original source code. 65226586Sdim const Expr* Expr = FullExpr->IgnoreImpCasts(); 66226586Sdim 67226586Sdim bool NeedParen = true; 68226586Sdim if (isa<ArraySubscriptExpr>(Expr) || 69226586Sdim isa<CallExpr>(Expr) || 70226586Sdim isa<DeclRefExpr>(Expr) || 71226586Sdim isa<CastExpr>(Expr) || 72226586Sdim isa<CXXNewExpr>(Expr) || 73226586Sdim isa<CXXConstructExpr>(Expr) || 74226586Sdim isa<CXXDeleteExpr>(Expr) || 75226586Sdim isa<CXXNoexceptExpr>(Expr) || 76226586Sdim isa<CXXPseudoDestructorExpr>(Expr) || 77226586Sdim isa<CXXScalarValueInitExpr>(Expr) || 78226586Sdim isa<CXXThisExpr>(Expr) || 79226586Sdim isa<CXXTypeidExpr>(Expr) || 80226586Sdim isa<CXXUnresolvedConstructExpr>(Expr) || 81226586Sdim isa<ObjCMessageExpr>(Expr) || 82226586Sdim isa<ObjCPropertyRefExpr>(Expr) || 83226586Sdim isa<ObjCProtocolExpr>(Expr) || 84226586Sdim isa<MemberExpr>(Expr) || 85226586Sdim isa<ParenExpr>(FullExpr) || 86226586Sdim isa<ParenListExpr>(Expr) || 87226586Sdim isa<SizeOfPackExpr>(Expr) || 88226586Sdim isa<UnaryOperator>(Expr)) 89226586Sdim NeedParen = false; 90226586Sdim 91226586Sdim // Check if the argument needs to be dereferenced: 92226586Sdim // (type * -> type) or (type * -> type &). 93226586Sdim if (const PointerType *FromPtrTy = dyn_cast<PointerType>(FromQTy)) { 94226586Sdim OverloadFixItKind FixKind = OFIK_Dereference; 95226586Sdim 96226586Sdim bool CanConvert = CompareTypes( 97226586Sdim S.Context.getCanonicalType(FromPtrTy->getPointeeType()), ToQTy, 98226586Sdim S, Begin, VK_LValue); 99226586Sdim if (CanConvert) { 100226586Sdim // Do not suggest dereferencing a Null pointer. 101226586Sdim if (Expr->IgnoreParenCasts()-> 102226586Sdim isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull)) 103226586Sdim return false; 104226586Sdim 105226586Sdim if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(Expr)) { 106226586Sdim if (UO->getOpcode() == UO_AddrOf) { 107226586Sdim FixKind = OFIK_RemoveTakeAddress; 108226586Sdim Hints.push_back(FixItHint::CreateRemoval( 109226586Sdim CharSourceRange::getTokenRange(Begin, Begin))); 110226586Sdim } 111226586Sdim } else if (NeedParen) { 112226586Sdim Hints.push_back(FixItHint::CreateInsertion(Begin, "*(")); 113226586Sdim Hints.push_back(FixItHint::CreateInsertion(End, ")")); 114226586Sdim } else { 115226586Sdim Hints.push_back(FixItHint::CreateInsertion(Begin, "*")); 116226586Sdim } 117226586Sdim 118226586Sdim NumConversionsFixed++; 119226586Sdim if (NumConversionsFixed == 1) 120226586Sdim Kind = FixKind; 121226586Sdim return true; 122226586Sdim } 123226586Sdim } 124226586Sdim 125226586Sdim // Check if the pointer to the argument needs to be passed: 126226586Sdim // (type -> type *) or (type & -> type *). 127226586Sdim if (isa<PointerType>(ToQTy)) { 128226586Sdim bool CanConvert = false; 129226586Sdim OverloadFixItKind FixKind = OFIK_TakeAddress; 130226586Sdim 131226586Sdim // Only suggest taking address of L-values. 132226586Sdim if (!Expr->isLValue() || Expr->getObjectKind() != OK_Ordinary) 133226586Sdim return false; 134226586Sdim 135226586Sdim CanConvert = CompareTypes(S.Context.getPointerType(FromQTy), ToQTy, 136226586Sdim S, Begin, VK_RValue); 137226586Sdim if (CanConvert) { 138226586Sdim 139226586Sdim if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(Expr)) { 140226586Sdim if (UO->getOpcode() == UO_Deref) { 141226586Sdim FixKind = OFIK_RemoveDereference; 142226586Sdim Hints.push_back(FixItHint::CreateRemoval( 143226586Sdim CharSourceRange::getTokenRange(Begin, Begin))); 144226586Sdim } 145226586Sdim } else if (NeedParen) { 146226586Sdim Hints.push_back(FixItHint::CreateInsertion(Begin, "&(")); 147226586Sdim Hints.push_back(FixItHint::CreateInsertion(End, ")")); 148226586Sdim } else { 149226586Sdim Hints.push_back(FixItHint::CreateInsertion(Begin, "&")); 150226586Sdim } 151226586Sdim 152226586Sdim NumConversionsFixed++; 153226586Sdim if (NumConversionsFixed == 1) 154226586Sdim Kind = FixKind; 155226586Sdim return true; 156226586Sdim } 157226586Sdim } 158226586Sdim 159226586Sdim return false; 160226586Sdim} 161