[clang] 179f4ba - Don't treat a CXXScopeSpec with a nested name specifier but no location

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 3 20:21:02 PDT 2020


Author: Richard Smith
Date: 2020-04-03T20:20:48-07:00
New Revision: 179f4baba0672a5e85c5db91095c4cd701a2d32d

URL: https://github.com/llvm/llvm-project/commit/179f4baba0672a5e85c5db91095c4cd701a2d32d
DIFF: https://github.com/llvm/llvm-project/commit/179f4baba0672a5e85c5db91095c4cd701a2d32d.diff

LOG: Don't treat a CXXScopeSpec with a nested name specifier but no location
as invalid.

We create those when forming trivial type source information with no
associated location, which, unfortunately, we do create in some cases
(when a TreeTransform with no base location is used to transform a
QualType).

This would previously lead to rejects-valid bugs when we misinterpreted
these constructs as having no nested-name-specifier.

Added: 
    

Modified: 
    clang/include/clang/Sema/DeclSpec.h
    clang/test/SemaCXX/nested-name-spec.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index 78010b7bb46e..0e95e237e974 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -186,14 +186,14 @@ class CXXScopeSpec {
   SourceLocation getLastQualifierNameLoc() const;
 
   /// No scope specifier.
-  bool isEmpty() const { return !Range.isValid(); }
+  bool isEmpty() const { return Range.isInvalid() && getScopeRep() == nullptr; }
   /// A scope specifier is present, but may be valid or invalid.
   bool isNotEmpty() const { return !isEmpty(); }
 
   /// An error occurred during parsing of the scope specifier.
-  bool isInvalid() const { return isNotEmpty() && getScopeRep() == nullptr; }
+  bool isInvalid() const { return Range.isValid() && getScopeRep() == nullptr; }
   /// A scope specifier is present, and it refers to a real scope.
-  bool isValid() const { return isNotEmpty() && getScopeRep() != nullptr; }
+  bool isValid() const { return getScopeRep() != nullptr; }
 
   /// Indicate that this nested-name-specifier is invalid.
   void SetInvalid(SourceRange R) {

diff  --git a/clang/test/SemaCXX/nested-name-spec.cpp b/clang/test/SemaCXX/nested-name-spec.cpp
index 725ac64cedb7..403bf1c0d4aa 100644
--- a/clang/test/SemaCXX/nested-name-spec.cpp
+++ b/clang/test/SemaCXX/nested-name-spec.cpp
@@ -460,3 +460,16 @@ class B {
 };
 }
 }
+
+namespace DependentTemplateInTrivialNNSLoc {
+  // This testcase causes us to create trivial type source info when doing
+  // substitution into T::template g<>. That trivial type source info contained
+  // a NestedNameSpecifierLoc with no location information.
+  //
+  // Previously, creating a CXXScopeSpec from that resulted in an invalid scope
+  // spec, leading to crashes. Ensure we don't crash here.
+  template <typename T> void f(T &x) {
+    for (typename T::template g<> i : x) {} // expected-warning 0-1{{extension}}
+    x: goto x;
+  }
+}


        


More information about the cfe-commits mailing list