From: Douglas Gregor Date: Thu, 19 Mar 2009 00:39:20 +0000 (+0000) Subject: Extend the use of QualifiedNameType to the creation of class template X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e6258936178b4c52b43b3b9dbec13552961cd645;p=clang Extend the use of QualifiedNameType to the creation of class template specialization names. This way, we keep track of sugared types like std::vector 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 --- diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 5106a54f95..3755744126 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -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. // diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 63d446f70c..483b79a098 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -87,13 +87,8 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, } else return 0; - if (SS && SS->isNotEmpty() && SS->isSet()) { - llvm::SmallVector 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(); } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index f5317787ba..b4e505e7c2 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -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: diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index a8be924fc8..24b32e8147 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -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 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); +} diff --git a/test/SemaCXX/qualified-names-diag.cpp b/test/SemaCXX/qualified-names-diag.cpp index 151b924a3a..c3bd47f9e5 100644 --- a/test/SemaCXX/qualified-names-diag.cpp +++ b/test/SemaCXX/qualified-names-diag.cpp @@ -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 index 0000000000..02bdf16b2b --- /dev/null +++ b/test/SemaTemplate/qualified-names-diag.cpp @@ -0,0 +1,16 @@ +// RUN: clang -fsyntax-only -verify %s + +namespace std { + template class vector { }; +} + +typedef int INT; +typedef float Real; + +void test() { + using namespace std; + + std::vector v1; + vector v2; + v1 = v2; // expected-error{{incompatible type assigning 'vector' (aka 'class vector'), expected 'std::vector' (aka 'class vector')}} +}