[cfe-commits] r81236 - in /cfe/trunk/lib: Frontend/PCHReader.cpp Frontend/PCHWriter.cpp Sema/Sema.cpp Sema/Sema.h Sema/SemaDecl.cpp

Chris Lattner sabre at nondot.org
Tue Sep 8 11:19:27 PDT 2009


Author: lattner
Date: Tue Sep  8 13:19:27 2009
New Revision: 81236

URL: http://llvm.org/viewvc/llvm-project?rev=81236&view=rev
Log:
Fix PR4922, where Sema would complete tentative definitions in nondeterminstic
order because it was doing so while iterating over a densemap.

There are still similar problems in other places, for example 
WeakUndeclaredIdentifiers is still written to the PCH file in a nondeterminstic
order, and we emit warnings about #pragma weak in nondeterminstic order.

Modified:
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp

Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=81236&r1=81235&r2=81236&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Tue Sep  8 13:19:27 2009
@@ -2225,6 +2225,7 @@
   for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {
     VarDecl *Var = cast<VarDecl>(GetDecl(TentativeDefinitions[I]));
     SemaObj->TentativeDefinitions[Var->getDeclName()] = Var;
+    SemaObj->TentativeDefinitionList.push_back(Var->getDeclName());
   }
 
   // If there were any locally-scoped external declarations,

Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=81236&r1=81235&r2=81236&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Tue Sep  8 13:19:27 2009
@@ -1800,19 +1800,22 @@
       getIdentifierRef(&Table.get(BuiltinNames[I]));
   }
 
-  // Build a record containing all of the tentative definitions in
-  // this header file. Generally, this record will be empty.
+  // Build a record containing all of the tentative definitions in this file, in
+  // TentativeDefinitionList order.  Generally, this record will be empty for
+  // headers.
   RecordData TentativeDefinitions;
-  for (llvm::DenseMap<DeclarationName, VarDecl *>::iterator 
-         TD = SemaRef.TentativeDefinitions.begin(),
-         TDEnd = SemaRef.TentativeDefinitions.end();
-       TD != TDEnd; ++TD)
-    AddDeclRef(TD->second, TentativeDefinitions);
+  for (unsigned i = 0, e = SemaRef.TentativeDefinitionList.size(); i != e; ++i){
+    VarDecl *VD =
+      SemaRef.TentativeDefinitions.lookup(SemaRef.TentativeDefinitionList[i]);
+    if (VD) AddDeclRef(VD, TentativeDefinitions);
+  }
 
   // Build a record containing all of the locally-scoped external
   // declarations in this header file. Generally, this record will be
   // empty.
   RecordData LocallyScopedExternalDecls;
+  // FIXME: This is filling in the PCH file in densemap order which is
+  // nondeterminstic!
   for (llvm::DenseMap<DeclarationName, NamedDecl *>::iterator 
          TD = SemaRef.LocallyScopedExternalDecls.begin(),
          TDEnd = SemaRef.LocallyScopedExternalDecls.end();

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=81236&r1=81235&r2=81236&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Tue Sep  8 13:19:27 2009
@@ -256,13 +256,16 @@
   // template instantiations earlier.
   PerformPendingImplicitInstantiations();
   
-  // check for #pragma weak identifiers that were never declared
+  // Check for #pragma weak identifiers that were never declared
+  // FIXME: This will cause diagnostics to be emitted in a non-determinstic
+  // order!  Iterating over a densemap like this is bad.
   for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator
-        I = WeakUndeclaredIdentifiers.begin(),
-        E = WeakUndeclaredIdentifiers.end(); I != E; ++I) {
-      if (!I->second.getUsed())
-        Diag(I->second.getLocation(), diag::warn_weak_identifier_undeclared)
-          << I->first;
+       I = WeakUndeclaredIdentifiers.begin(),
+       E = WeakUndeclaredIdentifiers.end(); I != E; ++I) {
+    if (I->second.getUsed()) continue;
+    
+    Diag(I->second.getLocation(), diag::warn_weak_identifier_undeclared)
+      << I->first;
   }
 
   if (!CompleteTranslationUnit)
@@ -279,31 +282,30 @@
   //   translation unit contains a file scope declaration of that
   //   identifier, with the composite type as of the end of the
   //   translation unit, with an initializer equal to 0.
-  for (llvm::DenseMap<DeclarationName, VarDecl *>::iterator 
-         D = TentativeDefinitions.begin(),
-         DEnd = TentativeDefinitions.end();
-       D != DEnd; ++D) {
-    VarDecl *VD = D->second;
-
-    if (VD->isInvalidDecl() || !VD->isTentativeDefinition(Context))
+  for (unsigned i = 0, e = TentativeDefinitionList.size(); i != e; ++i) {
+    VarDecl *VD = TentativeDefinitions.lookup(TentativeDefinitionList[i]);
+    
+    // If the tentative definition was completed, it will be in the list, but
+    // not the map.
+    if (VD == 0 || VD->isInvalidDecl() || !VD->isTentativeDefinition(Context))
       continue;
 
     if (const IncompleteArrayType *ArrayT 
         = Context.getAsIncompleteArrayType(VD->getType())) {
       if (RequireCompleteType(VD->getLocation(), 
                               ArrayT->getElementType(),
-                              diag::err_tentative_def_incomplete_type_arr))
+                              diag::err_tentative_def_incomplete_type_arr)) {
         VD->setInvalidDecl();
-      else {
-        // Set the length of the array to 1 (C99 6.9.2p5).
-        Diag(VD->getLocation(),  diag::warn_tentative_incomplete_array);
-        llvm::APInt One(Context.getTypeSize(Context.getSizeType()), 
-                        true);
-        QualType T 
-          = Context.getConstantArrayWithoutExprType(ArrayT->getElementType(),
-                                                    One, ArrayType::Normal, 0);
-        VD->setType(T);
+        continue;
       }
+      
+      // Set the length of the array to 1 (C99 6.9.2p5).
+      Diag(VD->getLocation(), diag::warn_tentative_incomplete_array);
+      llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true);
+      QualType T 
+        = Context.getConstantArrayWithoutExprType(ArrayT->getElementType(),
+                                                  One, ArrayType::Normal, 0);
+      VD->setType(T);
     } else if (RequireCompleteType(VD->getLocation(), VD->getType(), 
                                    diag::err_tentative_def_incomplete_type))
       VD->setInvalidDecl();

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=81236&r1=81235&r2=81236&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Sep  8 13:19:27 2009
@@ -266,6 +266,7 @@
   /// declaration, and only the most recent tentative declaration for
   /// a given variable will be recorded here.
   llvm::DenseMap<DeclarationName, VarDecl *> TentativeDefinitions;
+  std::vector<DeclarationName> TentativeDefinitionList;
 
   /// WeakUndeclaredIdentifiers - Identifiers contained in
   /// #pragma weak before declared. rare. may alias another

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=81236&r1=81235&r2=81236&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Sep  8 13:19:27 2009
@@ -3208,11 +3208,8 @@
   // remove it from the set of tentative definitions.
   if (VDecl->getPreviousDeclaration() &&
       VDecl->getPreviousDeclaration()->isTentativeDefinition(Context)) {
-    llvm::DenseMap<DeclarationName, VarDecl *>::iterator Pos 
-      = TentativeDefinitions.find(VDecl->getDeclName());
-    assert(Pos != TentativeDefinitions.end() && 
-           "Unrecorded tentative definition?");
-    TentativeDefinitions.erase(Pos);
+    bool Deleted = TentativeDefinitions.erase(VDecl->getDeclName());
+    assert(Deleted && "Unrecorded tentative definition?"); Deleted=Deleted;
   }
 
   return;
@@ -3230,8 +3227,20 @@
     QualType Type = Var->getType();
 
     // Record tentative definitions.
-    if (Var->isTentativeDefinition(Context))
-      TentativeDefinitions[Var->getDeclName()] = Var;
+    if (Var->isTentativeDefinition(Context)) {
+      std::pair<llvm::DenseMap<DeclarationName, VarDecl *>::iterator, bool>
+        InsertPair = 
+           TentativeDefinitions.insert(std::make_pair(Var->getDeclName(), Var));
+      
+      // Keep the latest definition in the map.  If we see 'int i; int i;' we
+      // want the second one in the map.
+      InsertPair.first->second = Var;
+
+      // However, for the list, we don't care about the order, just make sure
+      // that there are no dupes for a given declaration name.
+      if (InsertPair.second)
+        TentativeDefinitionList.push_back(Var->getDeclName());
+    }
 
     // C++ [dcl.init.ref]p3:
     //   The initializer can be omitted for a reference only in a





More information about the cfe-commits mailing list