r264466 - Store list of undefined-but-used objects in a deterministic order to fix

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 25 14:49:43 PDT 2016


Author: rsmith
Date: Fri Mar 25 16:49:43 2016
New Revision: 264466

URL: http://llvm.org/viewvc/llvm-project?rev=264466&view=rev
Log:
Store list of undefined-but-used objects in a deterministic order to fix
non-deterministic diagnostics (and non-deterministic PCH files). Check these
when building a module rather than serializing it; it's not reasonable for a
module's use to be satisfied by a definition in the user of the module.

Modified:
    cfe/trunk/include/clang/Sema/ExternalSemaSource.h
    cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Serialization/ASTReader.h
    cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/test/SemaCXX/diagnostic-order.cpp

Modified: cfe/trunk/include/clang/Sema/ExternalSemaSource.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ExternalSemaSource.h?rev=264466&r1=264465&r2=264466&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/ExternalSemaSource.h (original)
+++ cfe/trunk/include/clang/Sema/ExternalSemaSource.h Fri Mar 25 16:49:43 2016
@@ -77,8 +77,8 @@ public:
 
   /// \brief Load the set of used but not defined functions or variables with
   /// internal linkage, or used but not defined internal functions.
-  virtual void ReadUndefinedButUsed(
-                         llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined);
+  virtual void
+  ReadUndefinedButUsed(llvm::MapVector<NamedDecl *, SourceLocation> &Undefined);
 
   virtual void ReadMismatchingDeleteExpressions(llvm::MapVector<
       FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &);

Modified: cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h?rev=264466&r1=264465&r2=264466&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h (original)
+++ cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h Fri Mar 25 16:49:43 2016
@@ -211,7 +211,7 @@ public:
   /// \brief Load the set of used but not defined functions or variables with
   /// internal linkage, or used but not defined inline functions.
   void ReadUndefinedButUsed(
-                llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined) override;
+      llvm::MapVector<NamedDecl *, SourceLocation> &Undefined) override;
 
   void ReadMismatchingDeleteExpressions(llvm::MapVector<
       FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=264466&r1=264465&r2=264466&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Mar 25 16:49:43 2016
@@ -941,7 +941,7 @@ public:
 
   /// UndefinedInternals - all the used, undefined objects which require a
   /// definition in this translation unit.
-  llvm::DenseMap<NamedDecl *, SourceLocation> UndefinedButUsed;
+  llvm::MapVector<NamedDecl *, SourceLocation> UndefinedButUsed;
 
   /// Obtain a sorted list of functions that are undefined but ODR-used.
   void getUndefinedButUsed(

Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=264466&r1=264465&r2=264466&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Fri Mar 25 16:49:43 2016
@@ -1807,7 +1807,7 @@ public:
                          SmallVectorImpl<NamespaceDecl *> &Namespaces) override;
 
   void ReadUndefinedButUsed(
-               llvm::DenseMap<NamedDecl *, SourceLocation> &Undefined) override;
+      llvm::MapVector<NamedDecl *, SourceLocation> &Undefined) override;
 
   void ReadMismatchingDeleteExpressions(llvm::MapVector<
       FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &

Modified: cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp?rev=264466&r1=264465&r2=264466&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp (original)
+++ cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp Fri Mar 25 16:49:43 2016
@@ -204,7 +204,7 @@ void MultiplexExternalSemaSource::ReadKn
 }
 
 void MultiplexExternalSemaSource::ReadUndefinedButUsed(
-                         llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined){
+    llvm::MapVector<NamedDecl *, SourceLocation> &Undefined) {
   for(size_t i = 0; i < Sources.size(); ++i)
     Sources[i]->ReadUndefinedButUsed(Undefined);
 }

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=264466&r1=264465&r2=264466&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Fri Mar 25 16:49:43 2016
@@ -478,10 +478,8 @@ static bool ShouldRemoveFromUnused(Sema
 /// Obtains a sorted list of functions that are undefined but ODR-used.
 void Sema::getUndefinedButUsed(
     SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined) {
-  for (llvm::DenseMap<NamedDecl *, SourceLocation>::iterator
-         I = UndefinedButUsed.begin(), E = UndefinedButUsed.end();
-       I != E; ++I) {
-    NamedDecl *ND = I->first;
+  for (const auto &UndefinedUse : UndefinedButUsed) {
+    NamedDecl *ND = UndefinedUse.first;
 
     // Ignore attributes that have become invalid.
     if (ND->isInvalidDecl()) continue;
@@ -502,24 +500,8 @@ void Sema::getUndefinedButUsed(
         continue;
     }
 
-    Undefined.push_back(std::make_pair(ND, I->second));
+    Undefined.push_back(std::make_pair(ND, UndefinedUse.second));
   }
-
-  // Sort (in order of use site) so that we're not dependent on the iteration
-  // order through an llvm::DenseMap.
-  SourceManager &SM = Context.getSourceManager();
-  std::sort(Undefined.begin(), Undefined.end(),
-            [&SM](const std::pair<NamedDecl *, SourceLocation> &l,
-                  const std::pair<NamedDecl *, SourceLocation> &r) {
-    if (l.second.isValid() && !r.second.isValid())
-      return true;
-    if (!l.second.isValid() && r.second.isValid())
-      return false;
-    if (l.second != r.second)
-      return SM.isBeforeInTranslationUnit(l.second, r.second);
-    return SM.isBeforeInTranslationUnit(l.first->getLocation(),
-                                        r.first->getLocation());
-  });
 }
 
 /// checkUndefinedButUsed - Check for undefined objects with internal linkage
@@ -554,6 +536,8 @@ static void checkUndefinedButUsed(Sema &
     if (I->second.isValid())
       S.Diag(I->second, diag::note_used_here);
   }
+
+  S.UndefinedButUsed.clear();
 }
 
 void Sema::LoadExternalWeakUndeclaredIdentifiers() {
@@ -749,6 +733,12 @@ void Sema::ActOnEndOfTranslationUnit() {
       !Diags.isIgnored(diag::warn_delegating_ctor_cycle, SourceLocation()))
     CheckDelegatingCtorCycles();
 
+  if (!Diags.hasErrorOccurred()) {
+    if (ExternalSource)
+      ExternalSource->ReadUndefinedButUsed(UndefinedButUsed);
+    checkUndefinedButUsed(*this);
+  }
+
   if (TUKind == TU_Module) {
     // If we are building a module, resolve all of the exported declarations
     // now.
@@ -882,10 +872,6 @@ void Sema::ActOnEndOfTranslationUnit() {
       }
     }
 
-    if (ExternalSource)
-      ExternalSource->ReadUndefinedButUsed(UndefinedButUsed);
-    checkUndefinedButUsed(*this);
-
     emitAndClearUnusedLocalTypedefWarnings();
   }
 
@@ -1271,8 +1257,7 @@ void ExternalSemaSource::ReadKnownNamesp
 }
 
 void ExternalSemaSource::ReadUndefinedButUsed(
-                       llvm::DenseMap<NamedDecl *, SourceLocation> &Undefined) {
-}
+    llvm::MapVector<NamedDecl *, SourceLocation> &Undefined) {}
 
 void ExternalSemaSource::ReadMismatchingDeleteExpressions(llvm::MapVector<
     FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &) {}

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=264466&r1=264465&r2=264466&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Fri Mar 25 16:49:43 2016
@@ -7254,7 +7254,7 @@ void ASTReader::ReadKnownNamespaces(
 }
 
 void ASTReader::ReadUndefinedButUsed(
-                        llvm::DenseMap<NamedDecl*, SourceLocation> &Undefined) {
+    llvm::MapVector<NamedDecl *, SourceLocation> &Undefined) {
   for (unsigned Idx = 0, N = UndefinedButUsed.size(); Idx != N;) {
     NamedDecl *D = cast<NamedDecl>(GetDecl(UndefinedButUsed[Idx++]));
     SourceLocation Loc =

Modified: cfe/trunk/test/SemaCXX/diagnostic-order.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/diagnostic-order.cpp?rev=264466&r1=264465&r2=264466&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/diagnostic-order.cpp (original)
+++ cfe/trunk/test/SemaCXX/diagnostic-order.cpp Fri Mar 25 16:49:43 2016
@@ -1,4 +1,7 @@
-// RUN: not %clang_cc1 %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -std=c++11 %s -fsyntax-only 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 %s -fsyntax-only -DWARN 2>&1 | FileCheck %s --check-prefix=CHECK-WARN
+
+#ifndef WARN
 
 // Ensure that the diagnostics we produce for this situation appear in a
 // deterministic order. This requires ADL to provide lookup results in a
@@ -55,3 +58,16 @@ int *p = Oper() + 0;
 // CHECK: in instantiation of template class 'Error<Oper, X *>'
 // CHECK: no type named 'error' in 'Oper'
 // CHECK: in instantiation of template class 'Error<Oper, Y *>'
+
+#endif
+
+template<typename T> struct UndefButUsed {
+  static inline int f();
+  static int g() { return f(); }
+};
+int undef_but_used = UndefButUsed<int>::g() + UndefButUsed<float>::g() + UndefButUsed<char>::g() + UndefButUsed<void>::g();
+
+// CHECK-WARN: inline function 'UndefButUsed<int>::f' is not defined
+// CHECK-WARN: inline function 'UndefButUsed<float>::f' is not defined
+// CHECK-WARN: inline function 'UndefButUsed<char>::f' is not defined
+// CHECK-WARN: inline function 'UndefButUsed<void>::f' is not defined




More information about the cfe-commits mailing list