struct BuiltinTypeDeclBuilder {
CXXRecordDecl *Record = nullptr;
ClassTemplateDecl *Template = nullptr;
+ ClassTemplateDecl *PrevTemplate = nullptr;
NamespaceDecl *HLSLNamespace = nullptr;
llvm::StringMap<FieldDecl *> Fields;
ASTContext &AST = S.getASTContext();
IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
+ LookupResult Result(S, &II, SourceLocation(), Sema::LookupTagName);
+ CXXRecordDecl *PrevDecl = nullptr;
+ if (S.LookupQualifiedName(Result, HLSLNamespace)) {
+ NamedDecl *Found = Result.getFoundDecl();
+ if (auto *TD = dyn_cast<ClassTemplateDecl>(Found)) {
+ PrevDecl = TD->getTemplatedDecl();
+ PrevTemplate = TD;
+ } else
+ PrevDecl = dyn_cast<CXXRecordDecl>(Found);
+ assert(PrevDecl && "Unexpected lookup result type.");
+ }
+
+ if (PrevDecl && PrevDecl->isCompleteDefinition()) {
+ Record = PrevDecl;
+ return;
+ }
+
Record = CXXRecordDecl::Create(AST, TagDecl::TagKind::TTK_Class,
HLSLNamespace, SourceLocation(),
- SourceLocation(), &II, nullptr, true);
+ SourceLocation(), &II, PrevDecl, true);
Record->setImplicit(true);
Record->setLexicalDeclContext(HLSLNamespace);
Record->setHasExternalLexicalStorage();
- // Don't let anyone derive from built-in types
+ // Don't let anyone derive from built-in types.
Record->addAttr(FinalAttr::CreateImplicit(AST, SourceRange(),
AttributeCommonInfo::AS_Keyword,
FinalAttr::Keyword_final));
}
~BuiltinTypeDeclBuilder() {
- if (HLSLNamespace && !Template)
+ if (HLSLNamespace && !Template && Record->getDeclContext() == HLSLNamespace)
HLSLNamespace->addDecl(Record);
}
BuiltinTypeDeclBuilder &
- addTemplateArgumentList(llvm::ArrayRef<NamedDecl *> TemplateArgs) {
- ASTContext &AST = Record->getASTContext();
-
- auto *ParamList =
- TemplateParameterList::Create(AST, SourceLocation(), SourceLocation(),
- TemplateArgs, SourceLocation(), nullptr);
- Template = ClassTemplateDecl::Create(
- AST, Record->getDeclContext(), SourceLocation(),
- DeclarationName(Record->getIdentifier()), ParamList, Record);
- Record->setDescribedClassTemplate(Template);
- Template->setImplicit(true);
- Template->setLexicalDeclContext(Record->getDeclContext());
- Record->getDeclContext()->addDecl(Template);
-
- // Requesting the class name specialization will fault in required types.
- QualType T = Template->getInjectedClassNameSpecialization();
- T = AST.getInjectedClassNameType(Record, T);
- return *this;
- }
-
- BuiltinTypeDeclBuilder &
addMemberVariable(StringRef Name, QualType Type,
AccessSpecifier Access = AccessSpecifier::AS_private) {
+ if (Record->isCompleteDefinition())
+ return *this;
assert(Record->isBeingDefined() &&
"Definition must be started before adding members!");
ASTContext &AST = Record->getASTContext();
BuiltinTypeDeclBuilder &
addHandleMember(AccessSpecifier Access = AccessSpecifier::AS_private) {
+ if (Record->isCompleteDefinition())
+ return *this;
QualType Ty = Record->getASTContext().VoidPtrTy;
if (Template) {
if (const auto *TTD = dyn_cast<TemplateTypeParmDecl>(
BuiltinTypeDeclBuilder &
annotateResourceClass(HLSLResourceAttr::ResourceClass RC) {
+ if (Record->isCompleteDefinition())
+ return *this;
Record->addAttr(
HLSLResourceAttr::CreateImplicit(Record->getASTContext(), RC));
return *this;
BuiltinTypeDeclBuilder &addDefaultHandleConstructor(Sema &S,
ResourceClass RC) {
+ if (Record->isCompleteDefinition())
+ return *this;
ASTContext &AST = Record->getASTContext();
QualType ConstructorType =
}
BuiltinTypeDeclBuilder &addArraySubscriptOperators() {
+ if (Record->isCompleteDefinition())
+ return *this;
addArraySubscriptOperator(true);
addArraySubscriptOperator(false);
return *this;
}
BuiltinTypeDeclBuilder &addArraySubscriptOperator(bool IsConst) {
+ if (Record->isCompleteDefinition())
+ return *this;
assert(Fields.count("h") > 0 &&
"Subscript operator must be added after the handle.");
}
BuiltinTypeDeclBuilder &startDefinition() {
+ if (Record->isCompleteDefinition())
+ return *this;
Record->startDefinition();
return *this;
}
BuiltinTypeDeclBuilder &completeDefinition() {
+ if (Record->isCompleteDefinition())
+ return *this;
assert(Record->isBeingDefined() &&
"Definition must be started before completing it.");
TemplateParameterListBuilder &
addTypeParameter(StringRef Name, QualType DefaultValue = QualType()) {
+ if (Builder.Record->isCompleteDefinition())
+ return *this;
unsigned Position = static_cast<unsigned>(Params.size());
auto *Decl = TemplateTypeParmDecl::Create(
AST, Builder.Record->getDeclContext(), SourceLocation(),
Builder.Record->setDescribedClassTemplate(Builder.Template);
Builder.Template->setImplicit(true);
Builder.Template->setLexicalDeclContext(Builder.Record->getDeclContext());
+ // NOTE: setPreviousDecl before addDecl so new decl replace old decl when
+ // make visible.
+ Builder.Template->setPreviousDecl(Builder.PrevTemplate);
Builder.Record->getDeclContext()->addDecl(Builder.Template);
Params.clear();
void HLSLExternalSemaSource::InitializeSema(Sema &S) {
SemaPtr = &S;
ASTContext &AST = SemaPtr->getASTContext();
+ // If the translation unit has external storage force external decls to load.
+ if (AST.getTranslationUnitDecl()->hasExternalLexicalStorage())
+ (void)AST.getTranslationUnitDecl()->decls_begin();
+
IdentifierInfo &HLSL = AST.Idents.get("hlsl", tok::TokenKind::identifier);
- HLSLNamespace =
- NamespaceDecl::Create(AST, AST.getTranslationUnitDecl(), false,
- SourceLocation(), SourceLocation(), &HLSL, nullptr);
+ LookupResult Result(S, &HLSL, SourceLocation(), Sema::LookupNamespaceName);
+ NamespaceDecl *PrevDecl = nullptr;
+ if (S.LookupQualifiedName(Result, AST.getTranslationUnitDecl()))
+ PrevDecl = Result.getAsSingle<NamespaceDecl>();
+ HLSLNamespace = NamespaceDecl::Create(AST, AST.getTranslationUnitDecl(),
+ false, SourceLocation(),
+ SourceLocation(), &HLSL, PrevDecl);
HLSLNamespace->setImplicit(true);
+ HLSLNamespace->setHasExternalLexicalStorage();
AST.getTranslationUnitDecl()->addDecl(HLSLNamespace);
+
+ // Force external decls in the HLSL namespace to load from the PCH.
+ (void)HLSLNamespace->getCanonicalDecl()->decls_begin();
defineTrivialHLSLTypes();
forwardDeclareHLSLTypes();
.addTypeParameter("element_type", SemaPtr->getASTContext().FloatTy)
.finalizeTemplateArgs()
.Record;
- Completions.insert(std::make_pair(
- Decl, std::bind(&HLSLExternalSemaSource::completeBufferType, this,
- std::placeholders::_1)));
+ if (!Decl->isCompleteDefinition())
+ Completions.insert(
+ std::make_pair(Decl->getCanonicalDecl(),
+ std::bind(&HLSLExternalSemaSource::completeBufferType,
+ this, std::placeholders::_1)));
}
void HLSLExternalSemaSource::CompleteType(TagDecl *Tag) {
// declaration and complete that.
if (auto TDecl = dyn_cast<ClassTemplateSpecializationDecl>(Record))
Record = TDecl->getSpecializedTemplate()->getTemplatedDecl();
+ Record = Record->getCanonicalDecl();
auto It = Completions.find(Record);
if (It == Completions.end())
return;