From: Richard Smith Date: Fri, 20 Sep 2013 00:27:40 +0000 (+0000) Subject: PR17290: Use 'false' macro in fix-it hint for initializing a variable of type X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8adf837adc65b55a3f74643c02c1ee077dc26f06;p=clang PR17290: Use 'false' macro in fix-it hint for initializing a variable of type _Bool in C, if the macro is defined. Also teach FixItUtils to look at whether the macro was defined at the source location for which it is creating a fixit, rather than looking at whether it's defined *now*. This is especially relevant for analysis-based warnings which are delayed until end of TU. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191057 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index b914cb2b20..d39d8d5d55 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -949,8 +949,9 @@ public: bool findMacroSpelling(SourceLocation &loc, StringRef name); /// \brief Get a string to suggest for zero-initialization of a type. - std::string getFixItZeroInitializerForType(QualType T) const; - std::string getFixItZeroLiteralForType(QualType T) const; + std::string + getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const; + std::string getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const; ExprResult Owned(Expr* E) { return E; } ExprResult Owned(ExprResult R) { return R; } diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 7893a459c1..cc1cb0b342 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -439,22 +439,22 @@ static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) { << FixItHint::CreateInsertion(VD->getLocation(), "__block "); return true; } - + // Don't issue a fixit if there is already an initializer. if (VD->getInit()) return false; - - // Suggest possible initialization (if any). - std::string Init = S.getFixItZeroInitializerForType(VariableTy); - if (Init.empty()) - return false; // Don't suggest a fixit inside macros. if (VD->getLocEnd().isMacroID()) return false; SourceLocation Loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); - + + // Suggest possible initialization (if any). + std::string Init = S.getFixItZeroInitializerForType(VariableTy, Loc); + if (Init.empty()) + return false; + S.Diag(Loc, diag::note_var_fixit_add_initialization) << VD->getDeclName() << FixItHint::CreateInsertion(Loc, Init); return true; diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index a4fb3cfa45..426bf68e1d 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -5328,7 +5328,8 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if (!Loc.isMacroID() || CC.isMacroID()) S.Diag(Loc, diag::warn_impcast_null_pointer_to_integer) << T << clang::SourceRange(CC) - << FixItHint::CreateReplacement(Loc, S.getFixItZeroLiteralForType(T)); + << FixItHint::CreateReplacement(Loc, + S.getFixItZeroLiteralForType(T, Loc)); } if (!Source->isIntegerType() || !Target->isIntegerType()) diff --git a/lib/Sema/SemaFixItUtils.cpp b/lib/Sema/SemaFixItUtils.cpp index 2a845ba989..32b56bcddc 100644 --- a/lib/Sema/SemaFixItUtils.cpp +++ b/lib/Sema/SemaFixItUtils.cpp @@ -160,27 +160,33 @@ bool ConversionFixItGenerator::tryToFixConversion(const Expr *FullExpr, return false; } -static bool isMacroDefined(const Sema &S, StringRef Name) { - return S.PP.getMacroInfo(&S.getASTContext().Idents.get(Name)); +static bool isMacroDefined(const Sema &S, SourceLocation Loc, StringRef Name) { + const IdentifierInfo *II = &S.getASTContext().Idents.get(Name); + if (!II->hadMacroDefinition()) return false; + + MacroDirective *Macro = S.PP.getMacroDirectiveHistory(II); + return Macro && Macro->findDirectiveAtLoc(Loc, S.getSourceManager()); } -static std::string getScalarZeroExpressionForType(const Type& T, const Sema& S) { +static std::string getScalarZeroExpressionForType( + const Type &T, SourceLocation Loc, const Sema &S) { assert(T.isScalarType() && "use scalar types only"); // Suggest "0" for non-enumeration scalar types, unless we can find a // better initializer. if (T.isEnumeralType()) return std::string(); if ((T.isObjCObjectPointerType() || T.isBlockPointerType()) && - isMacroDefined(S, "nil")) + isMacroDefined(S, Loc, "nil")) return "nil"; if (T.isRealFloatingType()) return "0.0"; - if (T.isBooleanType() && S.LangOpts.CPlusPlus) + if (T.isBooleanType() && + (S.LangOpts.CPlusPlus || isMacroDefined(S, Loc, "false"))) return "false"; if (T.isPointerType() || T.isMemberPointerType()) { if (S.LangOpts.CPlusPlus11) return "nullptr"; - if (isMacroDefined(S, "NULL")) + if (isMacroDefined(S, Loc, "NULL")) return "NULL"; } if (T.isCharType()) @@ -194,9 +200,10 @@ static std::string getScalarZeroExpressionForType(const Type& T, const Sema& S) return "0"; } -std::string Sema::getFixItZeroInitializerForType(QualType T) const { +std::string +Sema::getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const { if (T->isScalarType()) { - std::string s = getScalarZeroExpressionForType(*T, *this); + std::string s = getScalarZeroExpressionForType(*T, Loc, *this); if (!s.empty()) s = " = " + s; return s; @@ -212,6 +219,7 @@ std::string Sema::getFixItZeroInitializerForType(QualType T) const { return std::string(); } -std::string Sema::getFixItZeroLiteralForType(QualType T) const { - return getScalarZeroExpressionForType(*T, *this); +std::string +Sema::getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const { + return getScalarZeroExpressionForType(*T, Loc, *this); } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 4cb4f5651f..753ce876d6 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -2395,7 +2395,8 @@ static void warnAboutAmbiguousFunction(Sema &S, Declarator &D, S.Diag(DeclType.Loc, diag::note_empty_parens_default_ctor) << FixItHint::CreateRemoval(ParenRange); else { - std::string Init = S.getFixItZeroInitializerForType(RT); + std::string Init = + S.getFixItZeroInitializerForType(RT, ParenRange.getBegin()); if (Init.empty() && S.LangOpts.CPlusPlus11) Init = "{}"; if (!Init.empty())