]> granicus.if.org Git - clang/commitdiff
[Modules] Make "#pragma weak" undeclared identifiers be tracked
authorChandler Carruth <chandlerc@gmail.com>
Thu, 26 Mar 2015 08:32:49 +0000 (08:32 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Thu, 26 Mar 2015 08:32:49 +0000 (08:32 +0000)
deterministically.

This fixes a latent issue where even Clang's Sema (and diagnostics) were
non-deterministic in the face of this pragma. The fix is super simple --
just use a MapVector so we track the order in which these are parsed (or
imported). Especially considering how rare they are, this seems like the
perfect tradeoff. I've also simplified the client code with judicious
use of auto and range based for loops.

I've added some pretty hilarious code to my stress test which now
survives the binary diff without issue.

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

include/clang/Sema/Sema.h
lib/Sema/Sema.cpp
lib/Sema/SemaDeclAttr.cpp
lib/Serialization/ASTWriter.cpp
test/Modules/Inputs/stress1/common.h
test/Modules/Inputs/stress1/merge00.h
test/Modules/stress1.cpp

index 9e07ad533f1e4041a750603cbda862e27358861a..dde928ff914e7c461e7d9f332add57b1a689af31 100644 (file)
@@ -592,7 +592,7 @@ public:
   /// WeakUndeclaredIdentifiers - Identifiers contained in
   /// \#pragma weak before declared. rare. may alias another
   /// identifier, declared or undeclared
-  llvm::DenseMap<IdentifierInfo*,WeakInfo> WeakUndeclaredIdentifiers;
+  llvm::MapVector<IdentifierInfo *, WeakInfo> WeakUndeclaredIdentifiers;
 
   /// ExtnameUndeclaredIdentifiers - Identifiers contained in
   /// \#pragma redefine_extname before declared.  Used in Solaris system headers
index a1a9b9d0b8c155da29680f8b263aaf9e7d34cee7..6825dfa41fa481588e82cb051295b4f08ad71af3 100644 (file)
@@ -524,14 +524,8 @@ void Sema::LoadExternalWeakUndeclaredIdentifiers() {
 
   SmallVector<std::pair<IdentifierInfo *, WeakInfo>, 4> WeakIDs;
   ExternalSource->ReadWeakUndeclaredIdentifiers(WeakIDs);
-  for (unsigned I = 0, N = WeakIDs.size(); I != N; ++I) {
-    llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator Pos
-      = WeakUndeclaredIdentifiers.find(WeakIDs[I].first);
-    if (Pos != WeakUndeclaredIdentifiers.end())
-      continue;
-
-    WeakUndeclaredIdentifiers.insert(WeakIDs[I]);
-  }
+  for (auto &WeakID : WeakIDs)
+    WeakUndeclaredIdentifiers.insert(WeakID);
 }
 
 
@@ -694,16 +688,13 @@ void Sema::ActOnEndOfTranslationUnit() {
   }
 
   // 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.
   LoadExternalWeakUndeclaredIdentifiers();
-  for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator
-       I = WeakUndeclaredIdentifiers.begin(),
-       E = WeakUndeclaredIdentifiers.end(); I != E; ++I) {
-    if (I->second.getUsed()) continue;
+  for (auto WeakID : WeakUndeclaredIdentifiers) {
+    if (WeakID.second.getUsed())
+      continue;
 
-    Diag(I->second.getLocation(), diag::warn_weak_identifier_undeclared)
-      << I->first;
+    Diag(WeakID.second.getLocation(), diag::warn_weak_identifier_undeclared)
+        << WeakID.first;
   }
 
   if (LangOpts.CPlusPlus11 &&
index 336d222f17e535fdbf2fe192d01ca0573518cef0..4ef62b9bb5d858534ba6d06eb636288e89acf958 100644 (file)
@@ -5019,8 +5019,7 @@ void Sema::ProcessPragmaWeak(Scope *S, Decl *D) {
         ND = FD;
     if (ND) {
       if (IdentifierInfo *Id = ND->getIdentifier()) {
-        llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator I
-          = WeakUndeclaredIdentifiers.find(Id);
+        auto I = WeakUndeclaredIdentifiers.find(Id);
         if (I != WeakUndeclaredIdentifiers.end()) {
           WeakInfo W = I->second;
           DeclApplyPragmaWeak(S, ND, W);
index 9f0626f060c4afcf7aa4ce35fff8a0d65b470eb7..7227a97e7b92414947c6634be378c672c3ebbcd3 100644 (file)
@@ -4359,15 +4359,13 @@ void ASTWriter::WriteASTCore(Sema &SemaRef,
   // entire table, since later PCH files in a PCH chain are only interested in
   // the results at the end of the chain.
   RecordData WeakUndeclaredIdentifiers;
-  if (!SemaRef.WeakUndeclaredIdentifiers.empty()) {
-    for (llvm::DenseMap<IdentifierInfo*,WeakInfo>::iterator
-         I = SemaRef.WeakUndeclaredIdentifiers.begin(),
-         E = SemaRef.WeakUndeclaredIdentifiers.end(); I != E; ++I) {
-      AddIdentifierRef(I->first, WeakUndeclaredIdentifiers);
-      AddIdentifierRef(I->second.getAlias(), WeakUndeclaredIdentifiers);
-      AddSourceLocation(I->second.getLocation(), WeakUndeclaredIdentifiers);
-      WeakUndeclaredIdentifiers.push_back(I->second.getUsed());
-    }
+  for (auto &WeakUndeclaredIdentifier : SemaRef.WeakUndeclaredIdentifiers) {
+    IdentifierInfo *II = WeakUndeclaredIdentifier.first;
+    WeakInfo &WI = WeakUndeclaredIdentifier.second;
+    AddIdentifierRef(II, WeakUndeclaredIdentifiers);
+    AddIdentifierRef(WI.getAlias(), WeakUndeclaredIdentifiers);
+    AddSourceLocation(WI.getLocation(), WeakUndeclaredIdentifiers);
+    WeakUndeclaredIdentifiers.push_back(WI.getUsed());
   }
 
   // Build a record containing all of the ext_vector declarations.
index d2fff1098d925e9fcf6f718491acc6cc93d62c08..b158a8e6c1e116aa2eaac31159206339b8b736ab 100644 (file)
@@ -35,4 +35,18 @@ struct S01 {};
 struct S02 {};
 }
 
+#pragma weak pragma_weak00
+#pragma weak pragma_weak01
+#pragma weak pragma_weak02
+#pragma weak pragma_weak03
+#pragma weak pragma_weak04
+#pragma weak pragma_weak05
+
+extern "C" int pragma_weak00();
+extern "C" int pragma_weak01();
+extern "C" int pragma_weak02();
+extern "C" int pragma_weak03;
+extern "C" int pragma_weak04;
+extern "C" int pragma_weak05;
+
 #endif
index c6dccdf53057c6bb8a91ece57e3f123bf9725b9c..b769b0877dd22feee17cf7ae2d0dd4396671dbcc 100644 (file)
@@ -1,6 +1,14 @@
 #ifndef STRESS1_MERGE00_H
 #define STRESS1_MERGE00_H
 
+// These don't match the imported declarations because we import them from
+// modules which are built in isolation of the current header's pragma state
+// much like they are built in isolation of the incoming macro state.
+// FIXME: We should expect warnings here but we can't because verify doesn't
+// work for modules.
+//#pragma weak pragma_weak01 // expected-warning {{weak identifier 'pragma_weak01' never declared}}
+//#pragma weak pragma_weak04 // expected-warning {{weak identifier 'pragma_waek04' never declared}}
+
 #include "m00.h"
 #include "m01.h"
 #include "m02.h"
@@ -8,4 +16,10 @@
 
 inline int g() { return N00::S00('a').method00('b') + (int)N00::S00(42) + function00(42); }
 
+#pragma weak pragma_weak02
+#pragma weak pragma_weak05
+
+extern "C" int pragma_weak02();
+int pragma_weak05;
+
 #endif
index 55d9533b7aeefce522981c998d4e7c2c0d04fbeb..e03e538a3ce504baf771b2b0277009cc32e87bf7 100644 (file)
@@ -98,3 +98,8 @@
 #include "merge00.h"
 
 int f() { return N01::S00('a').method00('b') + (int)N00::S00(42) + function00(42) + g(); }
+
+int f2() {
+  return pragma_weak00() + pragma_weak01() + pragma_weak02() +
+         pragma_weak03 + pragma_weak04 + pragma_weak05;
+}