From: David Blaikie Date: Mon, 30 Apr 2012 18:27:22 +0000 (+0000) Subject: Add FixItHint for -Wnull-conversion to initialize with an appropriate literal. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2c0abf4ae33ab2ba690ccae724b8d6f196e7cfda;p=clang Add FixItHint for -Wnull-conversion to initialize with an appropriate literal. Reviewed by Doug Gregor. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155839 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 252ea5b6d0..decde814eb 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -833,7 +833,8 @@ public: bool findMacroSpelling(SourceLocation &loc, StringRef name); /// \brief Get a string to suggest for zero-initialization of a type. - const char *getFixItZeroInitializerForType(QualType T) const; + std::string getFixItZeroInitializerForType(QualType T) const; + std::string getFixItZeroLiteralForType(QualType T) 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 9e577d9885..0288621928 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -438,8 +438,8 @@ static bool SuggestInitializationFixit(Sema &S, const VarDecl *VD) { return false; // Suggest possible initialization (if any). - const char *Init = S.getFixItZeroInitializerForType(VariableTy); - if (!Init) + std::string Init = S.getFixItZeroInitializerForType(VariableTy); + if (Init.empty()) return false; SourceLocation Loc = S.PP.getLocForEndOfToken(VD->getLocEnd()); diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index d12f707218..a9557a5474 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -4220,7 +4220,8 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if (Loc.isMacroID()) Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first; S.Diag(Loc, diag::warn_impcast_null_pointer_to_integer) - << T << Loc << clang::SourceRange(CC); + << T << clang::SourceRange(CC) + << FixItHint::CreateReplacement(Loc, S.getFixItZeroLiteralForType(T)); return; } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 6b18c98eca..ac28221e94 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5090,12 +5090,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, (RD->isEmpty() || RD->hasUserProvidedDefaultConstructor())) Diag(C.Loc, diag::note_empty_parens_default_ctor) << FixItHint::CreateRemoval(ParenRange); - else if (const char *Init = getFixItZeroInitializerForType(T)) - Diag(C.Loc, diag::note_empty_parens_zero_initialize) - << FixItHint::CreateReplacement(ParenRange, Init); - else if (LangOpts.CPlusPlus0x) - Diag(C.Loc, diag::note_empty_parens_zero_initialize) - << FixItHint::CreateReplacement(ParenRange, "{}"); + else { + std::string Init = getFixItZeroInitializerForType(T); + if (Init.empty() && LangOpts.CPlusPlus0x) + Init = "{}"; + if (!Init.empty()) + Diag(C.Loc, diag::note_empty_parens_zero_initialize) + << FixItHint::CreateReplacement(ParenRange, Init); + } } } diff --git a/lib/Sema/SemaFixItUtils.cpp b/lib/Sema/SemaFixItUtils.cpp index b78ea7d18e..fa99ef160a 100644 --- a/lib/Sema/SemaFixItUtils.cpp +++ b/lib/Sema/SemaFixItUtils.cpp @@ -163,42 +163,54 @@ static bool isMacroDefined(const Sema &S, StringRef Name) { return S.PP.getMacroInfo(&S.getASTContext().Idents.get(Name)); } -const char *Sema::getFixItZeroInitializerForType(QualType T) const { +static std::string getScalarZeroExpressionForType(const Type& T, 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")) + return "nil"; + if (T.isRealFloatingType()) + return "0.0"; + if (T.isBooleanType() && S.LangOpts.CPlusPlus) + return "false"; + if (T.isPointerType() || T.isMemberPointerType()) { + if (S.LangOpts.CPlusPlus0x) + return "nullptr"; + if (isMacroDefined(S, "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"; +} + +std::string 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"; + std::string s = getScalarZeroExpressionForType(*T, *this); + if (!s.empty()) + s = " = " + s; + return s; } const CXXRecordDecl *RD = T->getAsCXXRecordDecl(); if (!RD || !RD->hasDefinition()) - return 0; + return std::string(); if (LangOpts.CPlusPlus0x && !RD->hasUserProvidedDefaultConstructor()) return "{}"; if (RD->isAggregate()) return " = {}"; - return 0; + return std::string(); +} + +std::string Sema::getFixItZeroLiteralForType(QualType T) const { + return getScalarZeroExpressionForType(*T, *this); } diff --git a/test/FixIt/fixit.cpp b/test/FixIt/fixit.cpp index e9b4d75a6a..86a2dd4475 100644 --- a/test/FixIt/fixit.cpp +++ b/test/FixIt/fixit.cpp @@ -205,7 +205,6 @@ template Foo, // expected-error {{template template parameter template struct Baz> // expected-error {{template template parameter requires 'class' after the parameter list}} void func(); - namespace ShadowedTagType { class Foo { public: @@ -218,6 +217,9 @@ class Foo { void Foo::SetBar(Bar bar) { bar_ = bar; } // expected-error {{must use 'enum' tag to refer to type 'Bar' in this scope}} } +#define NULL __null +char c = NULL; // expected-warning {{implicit conversion of NULL constant to 'char'}} + namespace arrow_suggest { template