Extend the use of QualifiedNameType to the creation of class template
authorDouglas Gregor <dgregor@apple.com>
Thu, 19 Mar 2009 00:39:20 +0000 (00:39 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 19 Mar 2009 00:39:20 +0000 (00:39 +0000)
specialization names. This way, we keep track of sugared types like

  std::vector<Real>

I believe we are now using QualifiedNameTypes everywhere we can. Next
step: QualifiedDeclRefExprs.

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

lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaType.cpp
test/SemaCXX/qualified-names-diag.cpp
test/SemaTemplate/qualified-names-diag.cpp [new file with mode: 0644]

index 5106a54f952e181b21379948feb99622e0378db3..3755744126dc7b6e40c542741e3a88a5cce9620f 100644 (file)
@@ -295,6 +295,8 @@ public:
                               SourceRange Range2 = SourceRange(),
                               QualType PrintType = QualType());
 
+  QualType getQualifiedNameType(const CXXScopeSpec &SS, QualType T);
+
   //===--------------------------------------------------------------------===//
   // Symbol table / Decl tracking callbacks: SemaDecl.cpp.
   //
index 63d446f70c03df7e54fee23cb6a545e1cd2098dd..483b79a0984b6cb2632a4f06e342c032e1f698c3 100644 (file)
@@ -87,13 +87,8 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
     } else
       return 0;
 
-    if (SS && SS->isNotEmpty() && SS->isSet()) {
-      llvm::SmallVector<NestedNameSpecifier, 4> TNNs;
-      for (CXXScopeSpec::iterator TNN = SS->begin(), TNNEnd = SS->end();
-           TNN != TNNEnd; ++TNN)
-        TNNs.push_back(NestedNameSpecifier::getFromOpaquePtr(*TNN));
-      T = Context.getQualifiedNameType(&TNNs[0], TNNs.size(), T);
-    }
+    if (SS)
+      T = getQualifiedNameType(*SS, T);
 
     return T.getAsOpaquePtr();
   }
index f5317787bac2993ab94d66562c72ad8bbf7ddd50..b4e505e7c2fe99d214800463759047cef4325fbf 100644 (file)
@@ -765,6 +765,9 @@ Sema::ActOnClassTemplateId(DeclTy *TemplateD, SourceLocation TemplateLoc,
                                          &TemplateArgs[0],
                                          TemplateArgs.size(),
                                          RAngleLoc);
+  
+  if (SS)
+    Result = getQualifiedNameType(*SS, Result);
 
   TemplateArgsIn.release();
   return Result.getAsOpaquePtr();
@@ -1910,11 +1913,12 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
   // actually wrote the specialization, rather than formatting the
   // name based on the "canonical" representation used to store the
   // template arguments in the specialization.
-  Specialization->setTypeAsWritten(
-    Context.getClassTemplateSpecializationType(ClassTemplate, 
-                                               &TemplateArgs[0],
-                                               TemplateArgs.size(),
-                                  Context.getTypeDeclType(Specialization)));
+  QualType WrittenTy 
+    = Context.getClassTemplateSpecializationType(ClassTemplate, 
+                                                 &TemplateArgs[0],
+                                                 TemplateArgs.size(),
+                                  Context.getTypeDeclType(Specialization));
+  Specialization->setTypeAsWritten(getQualifiedNameType(SS, WrittenTy));
   TemplateArgsIn.release();
 
   // C++ [temp.expl.spec]p9:
index a8be924fc881e4bab944dfda59c5ddf5634e1b84..24b32e8147c85303a470862a0f0876e28f84679f 100644 (file)
@@ -1077,3 +1077,16 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, unsigned diag,
 
   return true;
 }
+
+/// \brief Retrieve a version of the type 'T' that is qualified by the
+/// nested-name-specifier contained in SS.
+QualType Sema::getQualifiedNameType(const CXXScopeSpec &SS, QualType T) {
+  if (!SS.isSet() || SS.isInvalid() || T.isNull())
+    return T;
+  
+  llvm::SmallVector<NestedNameSpecifier, 4> Specs;
+  for (CXXScopeSpec::iterator Spec = SS.begin(), SpecEnd = SS.end();
+       Spec != SpecEnd; ++Spec)
+    Specs.push_back(NestedNameSpecifier::getFromOpaquePtr(*Spec));
+  return Context.getQualifiedNameType(&Specs[0], Specs.size(), T);
+}
index 151b924a3af9c3d3246b6fe43a08cc3dc67c619f..c3bd47f9e5c2ce4fe308d91abfcee018fce3970b 100644 (file)
@@ -15,6 +15,8 @@ namespace foo {
 
 namespace bar {
   typedef int y;
+
+  struct incomplete; // expected-note{{forward declaration of 'struct incomplete'}}
 }
 void test() {
   foo::wibble::x a;
@@ -23,6 +25,9 @@ void test() {
 
   ::foo::wibble::bar::wonka::x::y c;
   c + b; // expected-error{{invalid operands to binary expression ('::foo::wibble::bar::wonka::x::y' (aka 'struct y') and '::bar::y' (aka 'int'))}}
+
+  (void)sizeof(bar::incomplete); // expected-error{{invalid application of 'sizeof' to an incomplete type 'bar::incomplete' (aka 'struct incomplete')}}
 }
 
 int ::foo::wibble::bar::wonka::x::y::* ptrmem;
+
diff --git a/test/SemaTemplate/qualified-names-diag.cpp b/test/SemaTemplate/qualified-names-diag.cpp
new file mode 100644 (file)
index 0000000..02bdf16
--- /dev/null
@@ -0,0 +1,16 @@
+// RUN: clang -fsyntax-only -verify %s
+
+namespace std {
+  template<typename T> class vector { };
+}
+
+typedef int INT;
+typedef float Real;
+
+void test() {
+  using namespace std;
+
+  std::vector<INT> v1;
+  vector<Real> v2;
+  v1 = v2; // expected-error{{incompatible type assigning 'vector<Real>' (aka 'class vector<float>'), expected 'std::vector<INT>' (aka 'class vector<int>')}}
+}