]> granicus.if.org Git - clang/commitdiff
Add missing -Wc++98-compat warnings for initializer list initializations which
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 19 Apr 2012 06:58:00 +0000 (06:58 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 19 Apr 2012 06:58:00 +0000 (06:58 +0000)
initialize references, create std::initializer_list objects, or call constructors.

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaInit.cpp
test/SemaCXX/cxx98-compat.cpp

index 86d42bb72ce17d71eb80e811d1800bc6d6baea5d..d9727746284dcd2de47cb3b9e3229d9fc02492f0 100644 (file)
@@ -3070,6 +3070,15 @@ def err_empty_scalar_initializer : Error<"scalar initializer cannot be empty">;
 def warn_cxx98_compat_empty_scalar_initializer : Warning<
   "scalar initialized from empty initializer list is incompatible with C++98">,
   InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx98_compat_reference_list_init : Warning<
+  "reference initialized from initializer list is incompatible with C++98">,
+  InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx98_compat_initializer_list_init : Warning<
+  "initialization of initializer_list object is incompatible with C++98">,
+  InGroup<CXX98Compat>, DefaultIgnore;
+def warn_cxx98_compat_ctor_list_init : Warning<
+  "constructor call from initializer list is incompatible with C++98">,
+  InGroup<CXX98Compat>, DefaultIgnore;
 def err_illegal_initializer : Error<
   "illegal initializer (only variables can be initialized)">;
 def err_illegal_initializer_type : Error<"illegal initializer type %0">;
index a65b41fd1cb676b08e8b15e1b19342e4ed15a479..4b80b77ecca47294dc334cee87a86bfd5dd93187 100644 (file)
@@ -4816,6 +4816,17 @@ InitializationSequence::Perform(Sema &S,
   if (Steps.empty())
     return S.Owned((Expr *)0);
 
+  if (S.getLangOpts().CPlusPlus0x && Entity.getType()->isReferenceType() &&
+      Args.size() == 1 && isa<InitListExpr>(Args.get()[0]) &&
+      Entity.getKind() != InitializedEntity::EK_Parameter) {
+    // Produce a C++98 compatibility warning if we are initializing a reference
+    // from an initializer list. For parameters, we produce a better warning
+    // elsewhere.
+    Expr *Init = Args.get()[0];
+    S.Diag(Init->getLocStart(), diag::warn_cxx98_compat_reference_list_init)
+      << Init->getSourceRange();
+  }
+
   QualType DestType = Entity.getType().getNonReferenceType();
   // FIXME: Ugly hack around the fact that Entity.getType() is not
   // the same as Entity.getDecl()->getType() in cases involving type merging,
@@ -5153,6 +5164,8 @@ InitializationSequence::Perform(Sema &S,
                                         Entity.getType().getNonReferenceType());
       bool UseTemporary = Entity.getType()->isReferenceType();
       InitListExpr *InitList = cast<InitListExpr>(CurInit.get());
+      S.Diag(InitList->getExprLoc(), diag::warn_cxx98_compat_ctor_list_init)
+        << InitList->getSourceRange();
       MultiExprArg Arg(InitList->getInits(), InitList->getNumInits());
       CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity :
                                                                    Entity,
@@ -5330,6 +5343,8 @@ InitializationSequence::Perform(Sema &S,
       }
 
       InitListExpr *ILE = cast<InitListExpr>(CurInit.take());
+      S.Diag(ILE->getExprLoc(), diag::warn_cxx98_compat_initializer_list_init)
+        << ILE->getSourceRange();
       unsigned NumInits = ILE->getNumInits();
       SmallVector<Expr*, 16> Converted(NumInits);
       InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(
index 47589135c9d5d96220716b1bc0506480503ca284..26882321220ebef3eb419a00aac20ed29f69429c 100644 (file)
@@ -1,7 +1,15 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wc++98-compat -verify %s
 // RUN: %clang_cc1 -fsyntax-only -std=c++11 %s
 
-namespace std { struct type_info; }
+namespace std {
+  struct type_info;
+  using size_t = decltype(sizeof(0)); // expected-warning {{decltype}} expected-warning {{alias}}
+  template<typename T> struct initializer_list {
+    initializer_list(T*, size_t);
+    T *p;
+    size_t n;
+  };
+}
 
 template<typename ...T>  // expected-warning {{variadic templates are incompatible with C++98}}
 class Variadic1 {};
@@ -39,6 +47,14 @@ void Lambda() {
   []{}(); // expected-warning {{lambda expressions are incompatible with C++98}}
 }
 
+struct Ctor {
+  Ctor(int, char);
+  Ctor(double, long);
+};
+struct InitListCtor {
+  InitListCtor(std::initializer_list<bool>);
+};
+
 int InitList(int i = {}) { // expected-warning {{generalized initializer lists are incompatible with C++98}} \
                            // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}}
   (void)new int {}; // expected-warning {{generalized initializer lists are incompatible with C++98}} \
@@ -48,6 +64,14 @@ int InitList(int i = {}) { // expected-warning {{generalized initializer lists a
   int x { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}}
   S<int> s = {}; // ok, aggregate
   s = {}; // expected-warning {{generalized initializer lists are incompatible with C++98}}
+  std::initializer_list<int> xs = { 1, 2, 3 }; // expected-warning {{initialization of initializer_list object is incompatible with C++98}}
+  auto ys = { 1, 2, 3 }; // expected-warning {{initialization of initializer_list object is incompatible with C++98}} \
+                         // expected-warning {{'auto' type specifier is incompatible with C++98}}
+  Ctor c1 = { 1, 2 }; // expected-warning {{constructor call from initializer list is incompatible with C++98}}
+  Ctor c2 = { 3.0, 4l }; // expected-warning {{constructor call from initializer list is incompatible with C++98}}
+  InitListCtor ilc = { true, false }; // expected-warning {{initialization of initializer_list object is incompatible with C++98}}
+  const int &r = { 0 }; // expected-warning {{reference initialized from initializer list is incompatible with C++98}}
+  struct { int a; const int &r; } rr = { 0, {{0}} }; // expected-warning {{reference initialized from initializer list is incompatible with C++98}}
   return { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}}
 }
 struct DelayedDefaultArgumentParseInitList {