From 222e2a7620e6520ffaf4fc4e69d79c18da31542e Mon Sep 17 00:00:00 2001 From: "Zancanaro; Carlo" Date: Mon, 24 Sep 2012 09:58:17 +1000 Subject: Add the clang library to the repo (with some of my changes, too). --- clang/lib/Sema/SemaFixItUtils.cpp | 204 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 clang/lib/Sema/SemaFixItUtils.cpp (limited to 'clang/lib/Sema/SemaFixItUtils.cpp') diff --git a/clang/lib/Sema/SemaFixItUtils.cpp b/clang/lib/Sema/SemaFixItUtils.cpp new file mode 100644 index 0000000..b78ea7d --- /dev/null +++ b/clang/lib/Sema/SemaFixItUtils.cpp @@ -0,0 +1,204 @@ +//===--- SemaFixItUtils.cpp - Sema FixIts ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines helper classes for generation of Sema FixItHints. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Sema.h" +#include "clang/Sema/SemaFixItUtils.h" + +using namespace clang; + +bool ConversionFixItGenerator::compareTypesSimple(CanQualType From, + CanQualType To, + Sema &S, + SourceLocation Loc, + ExprValueKind FromVK) { + if (!To.isAtLeastAsQualifiedAs(From)) + return false; + + From = From.getNonReferenceType(); + To = To.getNonReferenceType(); + + // If both are pointer types, work with the pointee types. + if (isa(From) && isa(To)) { + From = S.Context.getCanonicalType( + (cast(From))->getPointeeType()); + To = S.Context.getCanonicalType( + (cast(To))->getPointeeType()); + } + + const CanQualType FromUnq = From.getUnqualifiedType(); + const CanQualType ToUnq = To.getUnqualifiedType(); + + if ((FromUnq == ToUnq || (S.IsDerivedFrom(FromUnq, ToUnq)) ) && + To.isAtLeastAsQualifiedAs(From)) + return true; + return false; +} + +bool ConversionFixItGenerator::tryToFixConversion(const Expr *FullExpr, + const QualType FromTy, + const QualType ToTy, + Sema &S) { + if (!FullExpr) + return false; + + const CanQualType FromQTy = S.Context.getCanonicalType(FromTy); + const CanQualType ToQTy = S.Context.getCanonicalType(ToTy); + const SourceLocation Begin = FullExpr->getSourceRange().getBegin(); + const SourceLocation End = S.PP.getLocForEndOfToken(FullExpr->getSourceRange() + .getEnd()); + + // Strip the implicit casts - those are implied by the compiler, not the + // original source code. + const Expr* Expr = FullExpr->IgnoreImpCasts(); + + bool NeedParen = true; + if (isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(Expr) || + isa(FullExpr) || + isa(Expr) || + isa(Expr) || + isa(Expr)) + NeedParen = false; + + // Check if the argument needs to be dereferenced: + // (type * -> type) or (type * -> type &). + if (const PointerType *FromPtrTy = dyn_cast(FromQTy)) { + OverloadFixItKind FixKind = OFIK_Dereference; + + bool CanConvert = CompareTypes( + S.Context.getCanonicalType(FromPtrTy->getPointeeType()), ToQTy, + S, Begin, VK_LValue); + if (CanConvert) { + // Do not suggest dereferencing a Null pointer. + if (Expr->IgnoreParenCasts()-> + isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull)) + return false; + + if (const UnaryOperator *UO = dyn_cast(Expr)) { + if (UO->getOpcode() == UO_AddrOf) { + FixKind = OFIK_RemoveTakeAddress; + Hints.push_back(FixItHint::CreateRemoval( + CharSourceRange::getTokenRange(Begin, Begin))); + } + } else if (NeedParen) { + Hints.push_back(FixItHint::CreateInsertion(Begin, "*(")); + Hints.push_back(FixItHint::CreateInsertion(End, ")")); + } else { + Hints.push_back(FixItHint::CreateInsertion(Begin, "*")); + } + + NumConversionsFixed++; + if (NumConversionsFixed == 1) + Kind = FixKind; + return true; + } + } + + // Check if the pointer to the argument needs to be passed: + // (type -> type *) or (type & -> type *). + if (isa(ToQTy)) { + bool CanConvert = false; + OverloadFixItKind FixKind = OFIK_TakeAddress; + + // Only suggest taking address of L-values. + if (!Expr->isLValue() || Expr->getObjectKind() != OK_Ordinary) + return false; + + CanConvert = CompareTypes(S.Context.getPointerType(FromQTy), ToQTy, + S, Begin, VK_RValue); + if (CanConvert) { + + if (const UnaryOperator *UO = dyn_cast(Expr)) { + if (UO->getOpcode() == UO_Deref) { + FixKind = OFIK_RemoveDereference; + Hints.push_back(FixItHint::CreateRemoval( + CharSourceRange::getTokenRange(Begin, Begin))); + } + } else if (NeedParen) { + Hints.push_back(FixItHint::CreateInsertion(Begin, "&(")); + Hints.push_back(FixItHint::CreateInsertion(End, ")")); + } else { + Hints.push_back(FixItHint::CreateInsertion(Begin, "&")); + } + + NumConversionsFixed++; + if (NumConversionsFixed == 1) + Kind = FixKind; + return true; + } + } + + return false; +} + +static bool isMacroDefined(const Sema &S, StringRef Name) { + return S.PP.getMacroInfo(&S.getASTContext().Idents.get(Name)); +} + +const char *Sema::getFixItZeroInitializerForType(QualType T) const { + if (T->isScalarType()) { + // Suggest " = 0" for non-enumeration scalar types, unless we can find a + // better initializer. + if (T->isEnumeralType()) + return 0; + if ((T->isObjCObjectPointerType() || T->isBlockPointerType()) && + isMacroDefined(*this, "nil")) + return " = nil"; + if (T->isRealFloatingType()) + return " = 0.0"; + if (T->isBooleanType() && LangOpts.CPlusPlus) + return " = false"; + if (T->isPointerType() || T->isMemberPointerType()) { + if (LangOpts.CPlusPlus0x) + return " = nullptr"; + else if (isMacroDefined(*this, "NULL")) + return " = NULL"; + } + if (T->isCharType()) + return " = '\\0'"; + if (T->isWideCharType()) + return " = L'\\0'"; + if (T->isChar16Type()) + return " = u'\\0'"; + if (T->isChar32Type()) + return " = U'\\0'"; + return " = 0"; + } + + const CXXRecordDecl *RD = T->getAsCXXRecordDecl(); + if (!RD || !RD->hasDefinition()) + return 0; + if (LangOpts.CPlusPlus0x && !RD->hasUserProvidedDefaultConstructor()) + return "{}"; + if (RD->isAggregate()) + return " = {}"; + return 0; +} -- cgit v1.2.3