]> granicus.if.org Git - clang/commitdiff
When parsing typename specifiers (with either the identifier or
authorDouglas Gregor <dgregor@apple.com>
Wed, 2 Sep 2009 13:05:45 +0000 (13:05 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 2 Sep 2009 13:05:45 +0000 (13:05 +0000)
simple-template-id form), check whether the scope specifier is
computable as a declaration context rather than checking whether it is
dependent, so that we properly cope with members of the current
instantiation.

Improve testing for typename specifiers that terminate in a
simpe-template-id.

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

lib/AST/Type.cpp
lib/Sema/SemaTemplate.cpp
test/SemaTemplate/typename-specifier-4.cpp [new file with mode: 0644]

index bf506415ac645b83c237b3475addec1c8e3296e5..c6ea357fbd2e9b9704abb17ab62e06fcaa1d5320 100644 (file)
@@ -530,7 +530,7 @@ const TemplateSpecializationType *
 Type::getAsTemplateSpecializationType() const {
   // There is no sugar for class template specialization types, so
   // just return the canonical type pointer if it is the right class.
-  return dyn_cast<TemplateSpecializationType>(CanonicalType);
+  return this->getAs<TemplateSpecializationType>();
 }
 
 bool Type::isIntegerType() const {
index 3985c1c0e025a47e833e8bbeb12048c5044dc6ff..8566789ccdf0e91acdb240bc5b3755a02b2a1350 100644 (file)
@@ -1137,9 +1137,7 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc,
   NestedNameSpecifier *Qualifier 
     = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
 
-  // FIXME: member of the current instantiation
-
-  if (!Qualifier->isDependent()) {
+  if (computeDeclContext(SS, false)) {
     // C++0x [temp.names]p5:
     //   If a name prefixed by the keyword template is not the name of
     //   a template, the program is ill-formed. [Note: the keyword
@@ -3010,10 +3008,16 @@ Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS,
     = T->getAsTemplateSpecializationType();
   assert(TemplateId && "Expected a template specialization type");
 
-  if (NNS->isDependent())
-    return Context.getTypenameType(NNS, TemplateId).getAsOpaquePtr();
-
-  return Context.getQualifiedNameType(NNS, T).getAsOpaquePtr();
+  if (computeDeclContext(SS, false)) {
+    // If we can compute a declaration context, then the "typename"
+    // keyword was superfluous. Just build a QualifiedNameType to keep
+    // track of the nested-name-specifier.
+    
+    // FIXME: Note that the QualifiedNameType had the "typename" keyword!
+    return Context.getQualifiedNameType(NNS, T).getAsOpaquePtr();
+  }
+  
+  return Context.getTypenameType(NNS, TemplateId).getAsOpaquePtr();
 }
 
 /// \brief Build the type that describes a C++ typename specifier,
diff --git a/test/SemaTemplate/typename-specifier-4.cpp b/test/SemaTemplate/typename-specifier-4.cpp
new file mode 100644 (file)
index 0000000..2b1517e
--- /dev/null
@@ -0,0 +1,56 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<typename T, typename U> 
+struct is_same {
+  static const bool value = false;
+};
+
+template<typename T>
+struct is_same<T, T> {
+  static const bool value = true;
+};
+
+template<typename MetaFun, typename T1, typename T2>
+struct metafun_apply2 {
+  typedef typename MetaFun::template apply<T1, T2> inner;
+  typedef typename inner::type type;
+};
+
+template<typename T, typename U> struct pair;
+
+struct make_pair {
+  template<typename T1, typename T2>
+  struct apply {
+    typedef pair<T1, T2> type;
+  };
+};
+
+int a0[is_same<metafun_apply2<make_pair, int, float>::type, 
+               pair<int, float> >::value? 1 : -1];
+int a1[is_same<
+         typename make_pair::template apply<int, float>,
+         make_pair::apply<int, float>
+       >::value? 1 : -1];
+
+template<typename MetaFun>
+struct swap_and_apply2 {
+  template<typename T1, typename T2>
+  struct apply {
+    typedef typename MetaFun::template apply<T2, T1> new_metafun;
+    typedef typename new_metafun::type type;
+  };
+};
+
+int a2[is_same<swap_and_apply2<make_pair>::apply<int, float>::type, 
+               pair<float, int> >::value? 1 : -1];
+
+template<typename T>
+struct X0 {
+  template<typename U, typename V>
+  struct Inner;
+  
+  void f0(X0<T>::Inner<T*, T&>); // expected-note{{here}}
+  void f0(typename X0<T>::Inner<T*, T&>); // expected-error{{redecl}}
+
+  void f1(X0<T>::Inner<T*, T&>); // expected-note{{here}}
+  void f1(typename X0<T>::template Inner<T*, T&>); // expected-error{{redecl}}
+};