]> granicus.if.org Git - clang/commitdiff
Add FixItHint for -Wnull-conversion to initialize with an appropriate literal.
authorDavid Blaikie <dblaikie@gmail.com>
Mon, 30 Apr 2012 18:27:22 +0000 (18:27 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Mon, 30 Apr 2012 18:27:22 +0000 (18:27 +0000)
Reviewed by Doug Gregor.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155839 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Sema/AnalysisBasedWarnings.cpp
lib/Sema/SemaChecking.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaFixItUtils.cpp
test/FixIt/fixit.cpp

index 252ea5b6d0740b1900fd1a42caf8138a9ec433a3..decde814eb510346722146cc4e4c10eb8be35360 100644 (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; }
index 9e577d988551a26c7d66ae53d37b9d6a6c372554..02886219285507d6e1b5461c14d0be4a61fef0dc 100644 (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());
   
index d12f70721835938930868f8da794f407831984a2..a9557a5474a67af0cdeb5381c4c6c2971a860c54 100644 (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;
   }
 
index 6b18c98eca672ca13ea7f20ff53b240b54a2751d..ac28221e940fc5f6235564913a0e916622827eca 100644 (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);
+        }
       }
     }
 
index b78ea7d18ee77d4a38bf9c1238c9d4128fd28573..fa99ef160a3bae7ea953080021729995d3f2082a 100644 (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);
 }
index e9b4d75a6aa0b43e2933200af0d5bd0419b22dcd..86a2dd44754c7ebc313142c087555e143a1f76de 100644 (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>