[cfe-commits] r130887 - in /cfe/trunk: include/clang/Serialization/ASTBitCodes.h include/clang/Serialization/ASTReader.h lib/Sema/SemaDeclCXX.cpp lib/Serialization/ASTReader.cpp lib/Serialization/ASTWriter.cpp test/PCH/cxx0x-delegating-ctors.cpp test/PCH/cxx0x-delegating-ctors.h

Sean Hunt scshunt at csclub.uwaterloo.ca
Wed May 4 16:29:54 PDT 2011


Author: coppro
Date: Wed May  4 18:29:54 2011
New Revision: 130887

URL: http://llvm.org/viewvc/llvm-project?rev=130887&view=rev
Log:
there i fixed it

Increase robustness of the delegating constructor cycle detection
mechanism. No more infinite loops on invalid or logic errors leading to
false results. Ensure that this is maintained correctly accross
serialization.

Removed:
    cfe/trunk/test/PCH/cxx0x-delegating-ctors.h
Modified:
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
    cfe/trunk/include/clang/Serialization/ASTReader.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/PCH/cxx0x-delegating-ctors.cpp

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=130887&r1=130886&r2=130887&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Wed May  4 18:29:54 2011
@@ -362,7 +362,10 @@
       FP_PRAGMA_OPTIONS = 42,
 
       /// \brief Record code for enabled OpenCL extensions.
-      OPENCL_EXTENSIONS = 43
+      OPENCL_EXTENSIONS = 43,
+
+      /// \brief The list of delegating constructor declarations.
+      DELEGATING_CTORS = 44
     };
 
     /// \brief Record types used within a source manager block.

Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=130887&r1=130886&r2=130887&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Wed May  4 18:29:54 2011
@@ -54,6 +54,7 @@
 class DeclContext;
 class NestedNameSpecifier;
 class CXXBaseSpecifier;
+class CXXConstructorDecl;
 class CXXCtorInitializer;
 class GotoStmt;
 class MacroDefinition;
@@ -564,6 +565,10 @@
   /// generating warnings.
   llvm::SmallVector<uint64_t, 16> UnusedFileScopedDecls;
 
+  /// \brief A list of all the delegating constructors we've seen, to diagnose
+  /// cycles.
+  llvm::SmallVector<uint64_t, 4> DelegatingCtorDecls;
+
   /// \brief A snapshot of Sema's weak undeclared identifier tracking, for
   /// generating warnings.
   llvm::SmallVector<uint64_t, 64> WeakUndeclaredIdentifiers;

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=130887&r1=130886&r2=130887&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed May  4 18:29:54 2011
@@ -7945,52 +7945,85 @@
   }
 }
 
-void Sema::CheckDelegatingCtorCycles() {
-  llvm::SmallSet<CXXConstructorDecl*, 4> Valid, Invalid, Current;
+static
+void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
+                           llvm::SmallSet<CXXConstructorDecl*, 4> &Valid,
+                           llvm::SmallSet<CXXConstructorDecl*, 4> &Invalid,
+                           llvm::SmallSet<CXXConstructorDecl*, 4> &Current,
+                           Sema &S) {
+  llvm::SmallSet<CXXConstructorDecl*, 4>::iterator CI = Current.begin(),
+                                                   CE = Current.end();
+  if (Ctor->isInvalidDecl())
+    return;
 
-  llvm::SmallSet<CXXConstructorDecl*, 4>::iterator ci = Current.begin(),
-                                                   ce = Current.end();
+  const FunctionDecl *FNTarget = 0;
+  CXXConstructorDecl *Target;
+  
+  // We ignore the result here since if we don't have a body, Target will be
+  // null below.
+  (void)Ctor->getTargetConstructor()->hasBody(FNTarget);
+  Target
+= const_cast<CXXConstructorDecl*>(cast_or_null<CXXConstructorDecl>(FNTarget));
 
-  for (llvm::SmallVector<CXXConstructorDecl*, 4>::iterator
-         i = DelegatingCtorDecls.begin(),
-         e = DelegatingCtorDecls.end();
-       i != e; ++i) {
-    const FunctionDecl *FNTarget;
-    CXXConstructorDecl *Target;
-    (*i)->getTargetConstructor()->hasBody(FNTarget);
-    Target
-      = const_cast<CXXConstructorDecl*>(cast<CXXConstructorDecl>(FNTarget));
-
-    if (!Target || !Target->isDelegatingConstructor() || Valid.count(Target)) {
-      Valid.insert(*i);
-      for (ci = Current.begin(), ce = Current.end(); ci != ce; ++ci)
-        Valid.insert(*ci);
-      Current.clear();
-    } else if (Target == *i || Invalid.count(Target) || Current.count(Target)) {
-      if (!Invalid.count(Target)) {
-        Diag((*(*i)->init_begin())->getSourceLocation(),
+  CXXConstructorDecl *Canonical = Ctor->getCanonicalDecl(),
+                     // Avoid dereferencing a null pointer here.
+                     *TCanonical = Target ? Target->getCanonicalDecl() : 0;
+
+  if (!Current.insert(Canonical))
+    return;
+
+  // We know that beyond here, we aren't chaining into a cycle.
+  if (!Target || !Target->isDelegatingConstructor() ||
+      Target->isInvalidDecl() || Valid.count(TCanonical)) {
+    for (CI = Current.begin(), CE = Current.end(); CI != CE; ++CI)
+      Valid.insert(*CI);
+    Current.clear();
+  // We've hit a cycle.
+  } else if (TCanonical == Canonical || Invalid.count(TCanonical) ||
+             Current.count(TCanonical)) {
+    // If we haven't diagnosed this cycle yet, do so now.
+    if (!Invalid.count(TCanonical)) {
+      S.Diag((*Ctor->init_begin())->getSourceLocation(),
              diag::err_delegating_ctor_cycle)
-          << *i;
-        if (Target != *i)
-          Diag(Target->getLocation(), diag::note_it_delegates_to);
-        CXXConstructorDecl *Current = Target;
-        while (Current != *i) {
-          Current->getTargetConstructor()->hasBody(FNTarget);
-          Current
-         = const_cast<CXXConstructorDecl*>(cast<CXXConstructorDecl>(FNTarget));
-          Diag(Current->getLocation(), diag::note_which_delegates_to);
-        }
-      }
+        << Ctor;
+
+      // Don't add a note for a function delegating directo to itself.
+      if (TCanonical != Canonical)
+        S.Diag(Target->getLocation(), diag::note_it_delegates_to);
 
-      (*i)->setInvalidDecl();
-      Invalid.insert(*i);
-      for (ci = Current.begin(), ce = Current.end(); ci != ce; ++ci) {
-        (*ci)->setInvalidDecl();
-        Invalid.insert(*i);
+      CXXConstructorDecl *C = Target;
+      while (C->getCanonicalDecl() != Canonical) {
+        (void)C->getTargetConstructor()->hasBody(FNTarget);
+        assert(FNTarget && "Ctor cycle through bodiless function");
+
+        C
+       = const_cast<CXXConstructorDecl*>(cast<CXXConstructorDecl>(FNTarget));
+        S.Diag(C->getLocation(), diag::note_which_delegates_to);
       }
-      Current.clear();
-    } else {
-      Current.insert(*i);
     }
+
+    for (CI = Current.begin(), CE = Current.end(); CI != CE; ++CI)
+      Invalid.insert(*CI);
+    Current.clear();
+  } else {
+    DelegatingCycleHelper(Target, Valid, Invalid, Current, S);
   }
 }
+   
+
+void Sema::CheckDelegatingCtorCycles() {
+  llvm::SmallSet<CXXConstructorDecl*, 4> Valid, Invalid, Current;
+
+  llvm::SmallSet<CXXConstructorDecl*, 4>::iterator CI = Current.begin(),
+                                                   CE = Current.end();
+
+  for (llvm::SmallVector<CXXConstructorDecl*, 4>::iterator
+         I = DelegatingCtorDecls.begin(),
+         E = DelegatingCtorDecls.end();
+       I != E; ++I) {
+   DelegatingCycleHelper(*I, Valid, Invalid, Current, *this);
+  }
+
+  for (CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI)
+    (*CI)->setInvalidDecl();
+}

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=130887&r1=130886&r2=130887&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Wed May  4 18:29:54 2011
@@ -2114,15 +2114,6 @@
       TotalVisibleDeclContexts += Record[3];
       break;
 
-    case TENTATIVE_DEFINITIONS:
-      // Optimization for the first block.
-      if (TentativeDefinitions.empty())
-        TentativeDefinitions.swap(Record);
-      else
-        TentativeDefinitions.insert(TentativeDefinitions.end(),
-                                    Record.begin(), Record.end());
-      break;
-
     case UNUSED_FILESCOPED_DECLS:
       // Optimization for the first block.
       if (UnusedFileScopedDecls.empty())
@@ -2132,6 +2123,15 @@
                                      Record.begin(), Record.end());
       break;
 
+    case DELEGATING_CTORS:
+      // Optimization for the first block.
+      if (DelegatingCtorDecls.empty())
+        DelegatingCtorDecls.swap(Record);
+      else
+        DelegatingCtorDecls.insert(DelegatingCtorDecls.end(),
+                                   Record.begin(), Record.end());
+      break;
+
     case WEAK_UNDECLARED_IDENTIFIERS:
       // Later blocks overwrite earlier ones.
       WeakUndeclaredIdentifiers.swap(Record);
@@ -2331,6 +2331,15 @@
       // Later tables overwrite earlier ones.
       OpenCLExtensions.swap(Record);
       break;
+
+    case TENTATIVE_DEFINITIONS:
+      // Optimization for the first block.
+      if (TentativeDefinitions.empty())
+        TentativeDefinitions.swap(Record);
+      else
+        TentativeDefinitions.insert(TentativeDefinitions.end(),
+                                    Record.begin(), Record.end());
+      break;
     }
     First = false;
   }
@@ -4100,6 +4109,13 @@
     SemaObj->UnusedFileScopedDecls.push_back(D);
   }
 
+  // If there were any delegating constructors, add them to Sema's list
+  for (unsigned I = 0, N = DelegatingCtorDecls.size(); I != N; ++I) {
+    CXXConstructorDecl *D
+     = cast<CXXConstructorDecl>(GetDecl(DelegatingCtorDecls[I]));
+    SemaObj->DelegatingCtorDecls.push_back(D);
+  }
+
   // If there were any locally-scoped external declarations,
   // deserialize them and add them to Sema's table of locally-scoped
   // external declarations.

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=130887&r1=130886&r2=130887&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Wed May  4 18:29:54 2011
@@ -764,6 +764,7 @@
   RECORD(HEADER_SEARCH_TABLE);
   RECORD(FP_PRAGMA_OPTIONS);
   RECORD(OPENCL_EXTENSIONS);
+  RECORD(DELEGATING_CTORS);
   
   // SourceManager Block.
   BLOCK(SOURCE_MANAGER_BLOCK);
@@ -2723,6 +2724,10 @@
   for (unsigned i=0, e = SemaRef.UnusedFileScopedDecls.size(); i !=e; ++i)
     AddDeclRef(SemaRef.UnusedFileScopedDecls[i], UnusedFileScopedDecls);
 
+  RecordData DelegatingCtorDecls;
+  for (unsigned i=0, e = SemaRef.DelegatingCtorDecls.size(); i != e; ++i)
+    AddDeclRef(SemaRef.DelegatingCtorDecls[i], DelegatingCtorDecls);
+
   RecordData WeakUndeclaredIdentifiers;
   if (!SemaRef.WeakUndeclaredIdentifiers.empty()) {
     WeakUndeclaredIdentifiers.push_back(
@@ -2897,6 +2902,10 @@
   // Write the record containing CUDA-specific declaration references.
   if (!CUDASpecialDeclRefs.empty())
     Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs);
+  
+  // Write the delegating constructors.
+  if (!DelegatingCtorDecls.empty())
+    Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls);
 
   // Some simple statistics
   Record.clear();
@@ -2971,6 +2980,14 @@
       AddDeclRef(SemaRef.UnusedFileScopedDecls[i], UnusedFileScopedDecls);
   }
 
+  // Build a record containing all of the delegating constructor decls in this
+  // file.
+  RecordData DelegatingCtorDecls;
+  for (unsigned i=0, e = SemaRef.DelegatingCtorDecls.size(); i != e; ++i) {
+    if (SemaRef.DelegatingCtorDecls[i]->getPCHLevel() == 0)
+      AddDeclRef(SemaRef.DelegatingCtorDecls[i], DelegatingCtorDecls);
+  }
+
   // We write the entire table, overwriting the tables from the chain.
   RecordData WeakUndeclaredIdentifiers;
   if (!SemaRef.WeakUndeclaredIdentifiers.empty()) {
@@ -3128,6 +3145,10 @@
   // Write the record containing declaration references of Sema.
   if (!SemaDeclRefs.empty())
     Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs);
+  
+  // Write the delegating constructors.
+  if (!DelegatingCtorDecls.empty())
+    Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls);
 
   // Write the updates to DeclContexts.
   for (llvm::SmallPtrSet<const DeclContext *, 16>::iterator

Modified: cfe/trunk/test/PCH/cxx0x-delegating-ctors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx0x-delegating-ctors.cpp?rev=130887&r1=130886&r2=130887&view=diff
==============================================================================
--- cfe/trunk/test/PCH/cxx0x-delegating-ctors.cpp (original)
+++ cfe/trunk/test/PCH/cxx0x-delegating-ctors.cpp Wed May  4 18:29:54 2011
@@ -1,12 +1,20 @@
 // Test this without pch.
-// RUN: %clang_cc1 -include %S/cxx0x-delegating-ctors.h -std=c++0x -fsyntax-only -verify %s
+// RUN: %clang_cc1 -include %s -std=c++0x -fsyntax-only -verify %s
 
 // Test with pch.
-// RUN: %clang_cc1 -x c++-header -std=c++0x -emit-pch -o %t %S/cxx0x-delegating-ctors.h
+// RUN: %clang_cc1 -x c++-header -std=c++0x -emit-pch -o %t %s
 // RUN: %clang_cc1 -std=c++0x -include-pch %t -fsyntax-only -verify %s 
 
-// Currently we can't deal with a note in the header
-// XFAIL: *
-
+#ifndef PASS1
+#define PASS1
+struct foo {
+  foo(int) : foo() { } // expected-note{{it delegates to}}
+  foo();
+  foo(bool) : foo('c') { } // expected-note{{it delegates to}}
+  foo(char) : foo(true) { } // expected-error{{creates a delegation cycle}} \
+                            // expected-note{{which delegates to}}
+};
+#else
 foo::foo() : foo(1) { } // expected-error{{creates a delegation cycle}} \
                         // expected-note{{which delegates to}}
+#endif

Removed: cfe/trunk/test/PCH/cxx0x-delegating-ctors.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx0x-delegating-ctors.h?rev=130886&view=auto
==============================================================================
--- cfe/trunk/test/PCH/cxx0x-delegating-ctors.h (original)
+++ cfe/trunk/test/PCH/cxx0x-delegating-ctors.h (removed)
@@ -1,6 +0,0 @@
-// Header for PCH test cxx0x-delegating-ctors.cpp
-
-struct foo {
-  foo(int) : foo() { } // expected-note{{it delegates to}}
-  foo();
-};





More information about the cfe-commits mailing list