Add FixItHint for -Wnull-conversion to initialize with an appropriate literal.

Reviewed by Doug Gregor.

llvm-svn: 155839
This commit is contained in:
David Blaikie 2012-04-30 18:27:22 +00:00
parent f68e809c5e
commit 7665a62cf7
6 changed files with 58 additions and 40 deletions

View File

@ -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; }

View File

@ -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());

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -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);
}

View File

@ -205,7 +205,6 @@ template<template<typename> Foo, // expected-error {{template template parameter
template<typename> 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 <typename T>