diff options
| -rw-r--r-- | clang/include/clang/AST/Decl.h | 94 | ||||
| -rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 25 | ||||
| -rw-r--r-- | clang/lib/AST/Decl.cpp | 75 | ||||
| -rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/Frontend/PCHReaderDecl.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Frontend/PCHWriterDecl.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 18 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 8 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 10 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 64 | 
10 files changed, 281 insertions, 26 deletions
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index e9a991ecfed..e23811d8f9c 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -319,7 +319,19 @@ public:  /// \brief Represents a ValueDecl that came out of a declarator.  /// Contains type source information through TypeSourceInfo.  class DeclaratorDecl : public ValueDecl { -  TypeSourceInfo *DeclInfo; +  // A struct representing both a TInfo and a syntactic qualifier, +  // to be used for the (uncommon) case of out-of-line declarations. +  struct ExtInfo { +    TypeSourceInfo *TInfo; +    NestedNameSpecifier *NNS; +    SourceRange NNSRange; +  }; + +  llvm::PointerUnion<TypeSourceInfo*, ExtInfo*> DeclInfo; + +  bool hasExtInfo() const { return DeclInfo.is<ExtInfo*>(); } +  ExtInfo *getExtInfo() { return DeclInfo.get<ExtInfo*>(); } +  const ExtInfo *getExtInfo() const { return DeclInfo.get<ExtInfo*>(); }  protected:    DeclaratorDecl(Kind DK, DeclContext *DC, SourceLocation L, @@ -327,8 +339,29 @@ protected:      : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo) {}  public: -  TypeSourceInfo *getTypeSourceInfo() const { return DeclInfo; } -  void setTypeSourceInfo(TypeSourceInfo *TInfo) { DeclInfo = TInfo; } +  virtual ~DeclaratorDecl(); +  virtual void Destroy(ASTContext &C); + +  TypeSourceInfo *getTypeSourceInfo() const { +    return hasExtInfo() +      ? DeclInfo.get<ExtInfo*>()->TInfo +      : DeclInfo.get<TypeSourceInfo*>(); +  } +  void setTypeSourceInfo(TypeSourceInfo *TI) { +    if (hasExtInfo()) +      DeclInfo.get<ExtInfo*>()->TInfo = TI; +    else +      DeclInfo = TI; +  } + +  NestedNameSpecifier *getQualifier() const { +    return hasExtInfo() ? DeclInfo.get<ExtInfo*>()->NNS : 0; +  } +  SourceRange getQualifierRange() const { +    return hasExtInfo() ? DeclInfo.get<ExtInfo*>()->NNSRange : SourceRange(); +  } +  void setQualifierInfo(NestedNameSpecifier *Qualifier, +                        SourceRange QualifierRange);    SourceLocation getTypeSpecStartLoc() const; @@ -1534,22 +1567,38 @@ private:    /// IsEmbeddedInDeclarator - True if this tag declaration is    /// "embedded" (i.e., defined or declared for the very first time) -  /// in the syntax of a declarator, +  /// in the syntax of a declarator.    bool IsEmbeddedInDeclarator : 1; -  /// TypedefForAnonDecl - If a TagDecl is anonymous and part of a typedef, -  /// this points to the TypedefDecl. Used for mangling. -  TypedefDecl *TypedefForAnonDecl; -    SourceLocation TagKeywordLoc;    SourceLocation RBraceLoc; +  // A struct representing syntactic qualifier info, +  // to be used for the (uncommon) case of out-of-line declarations. +  struct ExtInfo { +    NestedNameSpecifier *NNS; +    SourceRange NNSRange; +  }; + +  /// TypedefDeclOrQualifier - If the (out-of-line) tag declaration name +  /// is qualified, it points to the qualifier info (nns and range); +  /// otherwise, if the tag declaration is anonymous and it is part of +  /// a typedef, it points to the TypedefDecl (used for mangling); +  /// otherwise, it is a null (TypedefDecl) pointer. +  llvm::PointerUnion<TypedefDecl*, ExtInfo*> TypedefDeclOrQualifier; + +  bool hasExtInfo() const { return TypedefDeclOrQualifier.is<ExtInfo*>(); } +  ExtInfo *getExtInfo() { return TypedefDeclOrQualifier.get<ExtInfo*>(); } +  const ExtInfo *getExtInfo() const { +    return TypedefDeclOrQualifier.get<ExtInfo*>(); +  } +  protected: -  TagDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, -          IdentifierInfo *Id, TagDecl *PrevDecl, -          SourceLocation TKL = SourceLocation()) -    : TypeDecl(DK, DC, L, Id), DeclContext(DK), TypedefForAnonDecl(0), -      TagKeywordLoc(TKL) { +  TagDecl(Kind DK, TagKind TK, DeclContext *DC, +          SourceLocation L, IdentifierInfo *Id, +          TagDecl *PrevDecl, SourceLocation TKL = SourceLocation()) +    : TypeDecl(DK, DC, L, Id), DeclContext(DK), TagKeywordLoc(TKL), +      TypedefDeclOrQualifier((TypedefDecl*) 0) {      assert((DK != Enum || TK == TK_enum) &&"EnumDecl not matched with TK_enum");      TagDeclKind = TK;      IsDefinition = false; @@ -1561,6 +1610,8 @@ protected:    virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); }  public: +  void Destroy(ASTContext &C); +    typedef redeclarable_base::redecl_iterator redecl_iterator;    redecl_iterator redecls_begin() const {      return redeclarable_base::redecls_begin(); @@ -1640,8 +1691,21 @@ public:    bool isUnion()  const { return getTagKind() == TK_union; }    bool isEnum()   const { return getTagKind() == TK_enum; } -  TypedefDecl *getTypedefForAnonDecl() const { return TypedefForAnonDecl; } -  void setTypedefForAnonDecl(TypedefDecl *TDD) { TypedefForAnonDecl = TDD; } +  TypedefDecl *getTypedefForAnonDecl() const { +    return hasExtInfo() ? 0 : TypedefDeclOrQualifier.get<TypedefDecl*>(); +  } +  void setTypedefForAnonDecl(TypedefDecl *TDD) { TypedefDeclOrQualifier = TDD; } + +  NestedNameSpecifier *getQualifier() const { +    return hasExtInfo() ? TypedefDeclOrQualifier.get<ExtInfo*>()->NNS : 0; +  } +  SourceRange getQualifierRange() const { +    return hasExtInfo() +      ? TypedefDeclOrQualifier.get<ExtInfo*>()->NNSRange +      : SourceRange(); +  } +  void setQualifierInfo(NestedNameSpecifier *Qualifier, +                        SourceRange QualifierRange);    // Implement isa/cast/dyncast/etc.    static bool classof(const Decl *D) { return classofKind(D->getKind()); } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 650bb53236b..3b4995958b9 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1592,6 +1592,12 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {                                        Name.getAsIdentifierInfo(),                                        Importer.Import(D->getTagKeywordLoc()),                                        0); +  // Import the qualifier, if any. +  if (D->getQualifier()) { +    NestedNameSpecifier *NNS = Importer.Import(D->getQualifier()); +    SourceRange NNSRange = Importer.Import(D->getQualifierRange()); +    D2->setQualifierInfo(NNS, NNSRange); +  }    D2->setAccess(D->getAccess());    D2->setLexicalDeclContext(LexicalDC);    Importer.Imported(D, D2); @@ -1734,6 +1740,12 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) {                                      Name.getAsIdentifierInfo(),                                       Importer.Import(D->getTagKeywordLoc()));      } +    // Import the qualifier, if any. +    if (D->getQualifier()) { +      NestedNameSpecifier *NNS = Importer.Import(D->getQualifier()); +      SourceRange NNSRange = Importer.Import(D->getQualifierRange()); +      D2->setQualifierInfo(NNS, NNSRange); +    }      D2->setLexicalDeclContext(LexicalDC);      LexicalDC->addDecl(D2);    } @@ -1900,6 +1912,13 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) {                                        D->isInlineSpecified(),                                        D->hasWrittenPrototype());    } + +  // Import the qualifier, if any. +  if (D->getQualifier()) { +    NestedNameSpecifier *NNS = Importer.Import(D->getQualifier()); +    SourceRange NNSRange = Importer.Import(D->getQualifierRange()); +    ToFunction->setQualifierInfo(NNS, NNSRange); +  }    ToFunction->setAccess(D->getAccess());    ToFunction->setLexicalDeclContext(LexicalDC);    Importer.Imported(D, ToFunction); @@ -2110,6 +2129,12 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) {    VarDecl *ToVar = VarDecl::Create(Importer.getToContext(), DC, Loc,                                      Name.getAsIdentifierInfo(), T, TInfo,                                     D->getStorageClass()); +  // Import the qualifier, if any. +  if (D->getQualifier()) { +    NestedNameSpecifier *NNS = Importer.Import(D->getQualifier()); +    SourceRange NNSRange = Importer.Import(D->getQualifierRange()); +    ToVar->setQualifierInfo(NNS, NNSRange); +  }    ToVar->setAccess(D->getAccess());    ToVar->setLexicalDeclContext(LexicalDC);    Importer.Imported(D, ToVar); diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 23f5fba437a..f568d1cdd45 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -495,9 +495,16 @@ NamedDecl *NamedDecl::getUnderlyingDecl() {  // DeclaratorDecl Implementation  //===----------------------------------------------------------------------===// +DeclaratorDecl::~DeclaratorDecl() {} +void DeclaratorDecl::Destroy(ASTContext &C) { +  if (hasExtInfo()) +    C.Deallocate(getExtInfo()); +  ValueDecl::Destroy(C); +} +  SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const {    if (DeclInfo) { -    TypeLoc TL = DeclInfo->getTypeLoc(); +    TypeLoc TL = getTypeSourceInfo()->getTypeLoc();      while (true) {        TypeLoc NextTL = TL.getNextTypeLoc();        if (!NextTL) @@ -508,6 +515,36 @@ SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const {    return SourceLocation();  } +void DeclaratorDecl::setQualifierInfo(NestedNameSpecifier *Qualifier, +                                      SourceRange QualifierRange) { +  if (Qualifier) { +    // Make sure the extended decl info is allocated. +    if (!hasExtInfo()) { +      // Save (non-extended) type source info pointer. +      TypeSourceInfo *savedTInfo = DeclInfo.get<TypeSourceInfo*>(); +      // Allocate external info struct. +      DeclInfo = new (getASTContext()) ExtInfo; +      // Restore savedTInfo into (extended) decl info. +      getExtInfo()->TInfo = savedTInfo; +    } +    // Set qualifier info. +    getExtInfo()->NNS = Qualifier; +    getExtInfo()->NNSRange = QualifierRange; +  } +  else { +    // Here Qualifier == 0, i.e., we are removing the qualifier (if any). +    assert(QualifierRange.isInvalid()); +    if (hasExtInfo()) { +      // Save type source info pointer. +      TypeSourceInfo *savedTInfo = getExtInfo()->TInfo; +      // Deallocate the extended decl info. +      getASTContext().Deallocate(getExtInfo()); +      // Restore savedTInfo into (non-extended) decl info. +      DeclInfo = savedTInfo; +    } +  } +} +  //===----------------------------------------------------------------------===//  // VarDecl Implementation  //===----------------------------------------------------------------------===// @@ -542,7 +579,7 @@ void VarDecl::Destroy(ASTContext& C) {      }    }    this->~VarDecl(); -  C.Deallocate((void *)this); +  DeclaratorDecl::Destroy(C);  }  VarDecl::~VarDecl() { @@ -818,7 +855,7 @@ void FunctionDecl::Destroy(ASTContext& C) {    C.Deallocate(ParamInfo); -  Decl::Destroy(C); +  DeclaratorDecl::Destroy(C);  }  void FunctionDecl::getNameForDiagnostic(std::string &S, @@ -1348,6 +1385,12 @@ bool FieldDecl::isAnonymousStructOrUnion() const {  // TagDecl Implementation  //===----------------------------------------------------------------------===// +void TagDecl::Destroy(ASTContext &C) { +  if (hasExtInfo()) +    C.Deallocate(getExtInfo()); +  TypeDecl::Destroy(C); +} +  SourceRange TagDecl::getSourceRange() const {    SourceLocation E = RBraceLoc.isValid() ? RBraceLoc : getLocation();    return SourceRange(TagKeywordLoc, E); @@ -1409,6 +1452,26 @@ TagDecl::TagKind TagDecl::getTagKindForTypeSpec(unsigned TypeSpec) {    }  } +void TagDecl::setQualifierInfo(NestedNameSpecifier *Qualifier, +                               SourceRange QualifierRange) { +  if (Qualifier) { +    // Make sure the extended qualifier info is allocated. +    if (!hasExtInfo()) +      TypedefDeclOrQualifier = new (getASTContext()) ExtInfo; +    // Set qualifier info. +    getExtInfo()->NNS = Qualifier; +    getExtInfo()->NNSRange = QualifierRange; +  } +  else { +    // Here Qualifier == 0, i.e., we are removing the qualifier (if any). +    assert(QualifierRange.isInvalid()); +    if (hasExtInfo()) { +      getASTContext().Deallocate(getExtInfo()); +      TypedefDeclOrQualifier = (TypedefDecl*) 0; +    } +  } +} +  //===----------------------------------------------------------------------===//  // EnumDecl Implementation  //===----------------------------------------------------------------------===// @@ -1422,7 +1485,7 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,  }  void EnumDecl::Destroy(ASTContext& C) { -  Decl::Destroy(C); +  TagDecl::Destroy(C);  }  void EnumDecl::completeDefinition(QualType NewType, @@ -1529,7 +1592,7 @@ void NamespaceDecl::Destroy(ASTContext& C) {    // together. They are all top-level Decls.    this->~NamespaceDecl(); -  C.Deallocate((void *)this); +  Decl::Destroy(C);  } @@ -1563,7 +1626,7 @@ EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,  void EnumConstantDecl::Destroy(ASTContext& C) {    if (Init) Init->Destroy(C); -  Decl::Destroy(C); +  ValueDecl::Destroy(C);  }  TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 6deadcce547..37f7479b36c 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -943,8 +943,7 @@ StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,  void StaticAssertDecl::Destroy(ASTContext& C) {    AssertExpr->Destroy(C);    Message->Destroy(C); -  this->~StaticAssertDecl(); -  C.Deallocate((void *)this); +  Decl::Destroy(C);  }  StaticAssertDecl::~StaticAssertDecl() { diff --git a/clang/lib/Frontend/PCHReaderDecl.cpp b/clang/lib/Frontend/PCHReaderDecl.cpp index 70aa0dd3c9f..f847becb15b 100644 --- a/clang/lib/Frontend/PCHReaderDecl.cpp +++ b/clang/lib/Frontend/PCHReaderDecl.cpp @@ -131,10 +131,11 @@ void PCHDeclReader::VisitTagDecl(TagDecl *TD) {    TD->setTagKind((TagDecl::TagKind)Record[Idx++]);    TD->setDefinition(Record[Idx++]);    TD->setEmbeddedInDeclarator(Record[Idx++]); -  TD->setTypedefForAnonDecl( -                    cast_or_null<TypedefDecl>(Reader.GetDecl(Record[Idx++])));    TD->setRBraceLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));    TD->setTagKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +  // FIXME: maybe read optional qualifier and its range. +  TD->setTypedefForAnonDecl( +                    cast_or_null<TypedefDecl>(Reader.GetDecl(Record[Idx++])));  }  void PCHDeclReader::VisitEnumDecl(EnumDecl *ED) { @@ -168,6 +169,7 @@ void PCHDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {    TypeSourceInfo *TInfo = Reader.GetTypeSourceInfo(Record, Idx);    if (TInfo)      DD->setTypeSourceInfo(TInfo); +  // FIXME: read optional qualifier and its range.  }  void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) { diff --git a/clang/lib/Frontend/PCHWriterDecl.cpp b/clang/lib/Frontend/PCHWriterDecl.cpp index d40658c3f9b..7917280295a 100644 --- a/clang/lib/Frontend/PCHWriterDecl.cpp +++ b/clang/lib/Frontend/PCHWriterDecl.cpp @@ -127,9 +127,10 @@ void PCHDeclWriter::VisitTagDecl(TagDecl *D) {    Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding    Record.push_back(D->isDefinition());    Record.push_back(D->isEmbeddedInDeclarator()); -  Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record);    Writer.AddSourceLocation(D->getRBraceLoc(), Record);    Writer.AddSourceLocation(D->getTagKeywordLoc(), Record); +  // FIXME: maybe write optional qualifier and its range. +  Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record);  }  void PCHDeclWriter::VisitEnumDecl(EnumDecl *D) { @@ -165,6 +166,7 @@ void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {  void PCHDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {    VisitValueDecl(D);    Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record); +  // FIXME: write optional qualifier and its range.  }  void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 7179f4bc6bb..dab7d883a1d 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2262,6 +2262,13 @@ isOutOfScopePreviousDeclaration(NamedDecl *PrevDecl, DeclContext *DC,    return true;  } +static void SetNestedNameSpecifier(DeclaratorDecl *DD, Declarator &D) { +  CXXScopeSpec &SS = D.getCXXScopeSpec(); +  if (!SS.isSet()) return; +  DD->setQualifierInfo(static_cast<NestedNameSpecifier*>(SS.getScopeRep()), +                       SS.getRange()); +} +  NamedDecl*  Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,                                QualType R, TypeSourceInfo *TInfo, @@ -2371,6 +2378,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,    if (D.isInvalidType())      NewVD->setInvalidDecl(); +  SetNestedNameSpecifier(NewVD, D); +    if (D.getDeclSpec().isThreadSpecified()) {      if (NewVD->hasLocalStorage())        Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_non_global); @@ -2799,6 +2808,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,    if (D.isInvalidType())      NewFD->setInvalidDecl(); +  SetNestedNameSpecifier(NewFD, D); +    // Set the lexical context. If the declarator has a C++    // scope specifier, or is the object of a friend declaration, the    // lexical context will be different from the semantic context. @@ -4847,6 +4858,13 @@ CreateNewDecl:                                 cast_or_null<RecordDecl>(PrevDecl));    } +  // Maybe add qualifier info. +  if (SS.isNotEmpty()) { +    NestedNameSpecifier *NNS +      = static_cast<NestedNameSpecifier*>(SS.getScopeRep()); +    New->setQualifierInfo(NNS, SS.getRange()); +  } +    if (Kind != TagDecl::TK_enum) {      // Handle #pragma pack: if the #pragma pack stack has non-default      // alignment, make up a packed attribute for this decl. These diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 242d66fa521..d369b773e8d 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1945,11 +1945,19 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II) {      NewD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(),                                  FD->getLocation(), DeclarationName(II),                                  FD->getType(), FD->getTypeSourceInfo()); +    if (FD->getQualifier()) { +      FunctionDecl *NewFD = cast<FunctionDecl>(NewD); +      NewFD->setQualifierInfo(FD->getQualifier(), FD->getQualifierRange()); +    }    } else if (VarDecl *VD = dyn_cast<VarDecl>(ND)) {      NewD = VarDecl::Create(VD->getASTContext(), VD->getDeclContext(),                             VD->getLocation(), II,                             VD->getType(), VD->getTypeSourceInfo(),                             VD->getStorageClass()); +    if (VD->getQualifier()) { +      VarDecl *NewVD = cast<VarDecl>(NewD); +      NewVD->setQualifierInfo(VD->getQualifier(), VD->getQualifierRange()); +    }    }    return NewD;  } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 79298acc229..434d5563e1b 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -697,6 +697,12 @@ Sema::ActOnTemplateParameterList(unsigned Depth,                                         RAngleLoc);  } +static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) { +  if (SS.isSet()) +    T->setQualifierInfo(static_cast<NestedNameSpecifier*>(SS.getScopeRep()), +                        SS.getRange()); +} +  Sema::DeclResult  Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,                           SourceLocation KWLoc, const CXXScopeSpec &SS, @@ -864,6 +870,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,                            PrevClassTemplate?                              PrevClassTemplate->getTemplatedDecl() : 0,                            /*DelayTypeCreation=*/true); +  SetNestedNameSpecifier(NewClass, SS);    ClassTemplateDecl *NewTemplate      = ClassTemplateDecl::Create(Context, SemanticContext, NameLoc, @@ -3491,6 +3498,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,                                                         TemplateArgs,                                                         CanonType,                                                         PrevPartial); +    SetNestedNameSpecifier(Partial, SS);      if (PrevPartial) {        ClassTemplate->getPartialSpecializations().RemoveNode(PrevPartial); @@ -3547,6 +3555,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,                                                  ClassTemplate,                                                  Converted,                                                  PrevDecl); +    SetNestedNameSpecifier(Specialization, SS);      if (PrevDecl) {        ClassTemplate->getSpecializations().RemoveNode(PrevDecl); @@ -4328,6 +4337,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,                                                  TemplateNameLoc,                                                  ClassTemplate,                                                  Converted, PrevDecl); +    SetNestedNameSpecifier(Specialization, SS);      if (PrevDecl) {        // Remove the previous declaration from the folding set, since we want diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index e8bcb8be89b..dbe041c4aad 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -97,6 +97,11 @@ namespace {      TemplateParameterList *        SubstTemplateParams(TemplateParameterList *List); + +    bool SubstQualifier(const DeclaratorDecl *OldDecl, +                        DeclaratorDecl *NewDecl); +    bool SubstQualifier(const TagDecl *OldDecl, +                        TagDecl *NewDecl);      bool InstantiateClassTemplatePartialSpecialization(                                                ClassTemplateDecl *ClassTemplate, @@ -104,6 +109,38 @@ namespace {    };  } +bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl, +                                              DeclaratorDecl *NewDecl) { +  NestedNameSpecifier *OldQual = OldDecl->getQualifier(); +  if (!OldQual) return false; + +  SourceRange QualRange = OldDecl->getQualifierRange(); + +  NestedNameSpecifier *NewQual +    = SemaRef.SubstNestedNameSpecifier(OldQual, QualRange, TemplateArgs); +  if (!NewQual) +    return true; + +  NewDecl->setQualifierInfo(NewQual, QualRange); +  return false; +} + +bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl, +                                              TagDecl *NewDecl) { +  NestedNameSpecifier *OldQual = OldDecl->getQualifier(); +  if (!OldQual) return false; + +  SourceRange QualRange = OldDecl->getQualifierRange(); + +  NestedNameSpecifier *NewQual +    = SemaRef.SubstNestedNameSpecifier(OldQual, QualRange, TemplateArgs); +  if (!NewQual) +    return true; + +  NewDecl->setQualifierInfo(NewQual, QualRange); +  return false; +} +  // FIXME: Is this too simple?  void TemplateDeclInstantiator::InstantiateAttrs(Decl *Tmpl, Decl *New) {    for (const Attr *TmplAttr = Tmpl->getAttrs(); TmplAttr;  @@ -287,6 +324,10 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {    Var->setCXXDirectInitializer(D->hasCXXDirectInitializer());    Var->setDeclaredInCondition(D->isDeclaredInCondition()); +  // Substitute the nested name specifier, if any. +  if (SubstQualifier(D, Var)) +    return 0; +    // If we are instantiating a static data member defined    // out-of-line, the instantiation will have the same lexical    // context (which will be a namespace scope) as the template. @@ -511,6 +552,7 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {                                      /*PrevDecl=*/0);    Enum->setInstantiationOfMemberEnum(D);    Enum->setAccess(D->getAccess()); +  if (SubstQualifier(D, Enum)) return 0;    Owner->addDecl(Enum);    Enum->startDefinition(); @@ -611,6 +653,10 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {                              Pattern->getTagKeywordLoc(), /*PrevDecl=*/ NULL,                              /*DelayTypeCreation=*/true); +  // Substitute the nested name specifier, if any. +  if (SubstQualifier(Pattern, RecordInst)) +    return 0; +    ClassTemplateDecl *Inst      = ClassTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(),                                  D->getIdentifier(), InstParams, RecordInst, 0); @@ -745,6 +791,11 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {      = CXXRecordDecl::Create(SemaRef.Context, D->getTagKind(), Owner,                              D->getLocation(), D->getIdentifier(),                              D->getTagKeywordLoc(), PrevDecl); + +  // Substitute the nested name specifier, if any. +  if (SubstQualifier(D, Record)) +    return 0; +    Record->setImplicit(D->isImplicit());    // FIXME: Check against AS_none is an ugly hack to work around the issue that    // the tag decls introduced by friend class declarations don't have an access @@ -818,6 +869,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,                             D->getDeclName(), T, TInfo,                             D->getStorageClass(),                             D->isInlineSpecified(), D->hasWrittenPrototype()); + +  // Substitute the nested name specifier, if any. +  if (SubstQualifier(D, Function)) +    return 0; +    Function->setLexicalDeclContext(Owner);    // Attach the parameters @@ -979,6 +1035,10 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,                                     D->isStatic(), D->isInlineSpecified());    } +  // Substitute the nested name specifier, if any. +  if (SubstQualifier(D, Method)) +    return 0; +    if (TemplateParams) {      // Our resulting instantiation is actually a function template, since we      // are substituting only the outer template parameters. For example, given @@ -1508,6 +1568,10 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(                                                       InstTemplateArgs,                                                       CanonType,                                                       0); +  // Substitute the nested name specifier, if any. +  if (SubstQualifier(PartialSpec, InstPartialSpec)) +    return 0; +    InstPartialSpec->setInstantiatedFromMember(PartialSpec);    InstPartialSpec->setTypeAsWritten(WrittenTy);  | 

