r212238 - Enable clang to continue to parse libstdc++4.6 and stlport after r210091.

Nico Weber nicolasweber at gmx.de
Wed Jul 2 16:51:09 PDT 2014


Author: nico
Date: Wed Jul  2 18:51:09 2014
New Revision: 212238

URL: http://llvm.org/viewvc/llvm-project?rev=212238&view=rev
Log:
Enable clang to continue to parse libstdc++4.6 and stlport after r210091.

r210091 made initialization checking more strict in c++11 mode. LWG2193 is
about changing standard libraries to still be valid under these new rules,
but older libstdc++ (e.g. libstdc++4.6 in -D_GLIBCXX_DEBUG=1 mode, or stlport)
do not implement that yet.  So fall back to the C++03 semantics for container
classes in system headers below the std namespace.

Added:
    cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist-system-header.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaInit.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=212238&r1=212237&r2=212238&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Jul  2 18:51:09 2014
@@ -2128,6 +2128,10 @@ def err_attribute_dllimport_static_field
 def warn_attribute_dllimport_static_field_definition : Warning<
   "definition of dllimport static field">,
   InGroup<DiagGroup<"dllimport-static-field-def">>;
+def warn_invalid_initializer_from_system_header : Warning<
+  "invalid constructor form class in system header, should not be explicit">,
+  InGroup<DiagGroup<"invalid-initializer-from-system-header">>;
+def note_used_in_initialization_here : Note<"used in initialization here">;
 def err_attribute_dll_member_of_dll_class : Error<
   "attribute %q0 cannot be applied to member of %q1 class">;
 def warn_attribute_dll_instantiated_base_class : Warning<

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=212238&r1=212237&r2=212238&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Wed Jul  2 18:51:09 2014
@@ -353,8 +353,9 @@ ExprResult InitListChecker::PerformEmpty
   //   If there are fewer initializer-clauses in the list than there are
   //   members in the aggregate, then each member not explicitly initialized
   //   ...
-  if (SemaRef.getLangOpts().CPlusPlus11 &&
-      Entity.getType()->getBaseElementTypeUnsafe()->isRecordType()) {
+  bool EmptyInitList = SemaRef.getLangOpts().CPlusPlus11 &&
+      Entity.getType()->getBaseElementTypeUnsafe()->isRecordType();
+  if (EmptyInitList) {
     // C++1y / DR1070:
     //   shall be initialized [...] from an empty initializer list.
     //
@@ -376,6 +377,56 @@ ExprResult InitListChecker::PerformEmpty
   }
 
   InitializationSequence InitSeq(SemaRef, Entity, Kind, SubInit);
+  // libstdc++4.6 marks the vector default constructor as explicit in
+  // _GLIBCXX_DEBUG mode, so recover using the C++03 logic in that case.
+  // stlport does so too. Look for std::__debug for libstdc++, and for
+  // std:: for stlport.  This is effectively a compiler-side implementation of
+  // LWG2193.
+  if (!InitSeq && EmptyInitList && InitSeq.getFailureKind() ==
+          InitializationSequence::FK_ExplicitConstructor) {
+    OverloadCandidateSet::iterator Best;
+    OverloadingResult O =
+        InitSeq.getFailedCandidateSet()
+            .BestViableFunction(SemaRef, Kind.getLocation(), Best);
+    (void)O;
+    assert(O == OR_Success && "Inconsistent overload resolution");
+    CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
+    CXXRecordDecl *R = CtorDecl->getParent();
+
+    if (CtorDecl->getMinRequiredArguments() == 0 &&
+        CtorDecl->isExplicit() && R->getDeclName() &&
+        SemaRef.SourceMgr.isInSystemHeader(CtorDecl->getLocation())) {
+
+
+      bool IsInStd = false;
+      for (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(R->getDeclContext());
+           ND && !IsInStd;
+	   ND = dyn_cast<NamespaceDecl>(ND->getLexicalParent())) {
+        if (SemaRef.getStdNamespace()->InEnclosingNamespaceSetOf(ND))
+          IsInStd = true;
+      }
+
+      if (IsInStd && llvm::StringSwitch<bool>(R->getName()) 
+              .Cases("basic_string", "deque", "forward_list", true)
+              .Cases("list", "map", "multimap", "multiset", true)
+              .Cases("priority_queue", "queue", "set", "stack", true)
+              .Cases("unordered_map", "unordered_set", "vector", true)
+              .Default(false)) {
+        InitSeq.InitializeFrom(
+            SemaRef, Entity,
+            InitializationKind::CreateValue(Loc, Loc, Loc, true),
+            MultiExprArg(), /*TopLevelOfInitList=*/false);
+        // Emit a warning for this.  System header warnings aren't shown
+        // by default, but people working on system headers should see it.
+        if (!VerifyOnly) {
+          SemaRef.Diag(CtorDecl->getLocation(),
+                       diag::warn_invalid_initializer_from_system_header);
+          SemaRef.Diag(Entity.getDecl()->getLocation(),
+                       diag::note_used_in_initialization_here);
+        }
+      }
+    }
+  }
   if (!InitSeq) {
     if (!VerifyOnly) {
       InitSeq.Diagnose(SemaRef, Entity, Kind, SubInit);

Added: cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist-system-header.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist-system-header.cpp?rev=212238&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist-system-header.cpp (added)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist-system-header.cpp Wed Jul  2 18:51:09 2014
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wsystem-headers %s
+
+// libstdc++4.6 in debug mode has explicit default constructors.
+// stlport has this for all containers.
+#ifdef BE_THE_HEADER
+#pragma clang system_header
+namespace std {
+namespace __debug {
+template <class T>
+class vector {
+public:
+  explicit vector() {} // expected-warning{{should not be explicit}}
+};
+}
+}
+#else
+
+#define BE_THE_HEADER
+#include __FILE__
+
+struct { int a, b; std::__debug::vector<int> c; } e[] = { {1, 1} }; // expected-note{{used in initialization here}}
+
+#endif





More information about the cfe-commits mailing list