diff options
author | Reid Kleckner <rnk@google.com> | 2017-01-05 01:08:22 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2017-01-05 01:08:22 +0000 |
commit | 61195e12fc5cc128e5908cfb76a91ee6860659e5 (patch) | |
tree | c994eb649f4e21593a69010a16af1de5bb536def /clang/lib | |
parent | 87ea8c60a6d1346182dceebe15e392e83b7b50c0 (diff) | |
download | bcm5719-llvm-61195e12fc5cc128e5908cfb76a91ee6860659e5.tar.gz bcm5719-llvm-61195e12fc5cc128e5908cfb76a91ee6860659e5.zip |
[MS] Instantiate default args during instantiation of exported default ctors
Summary:
Replace some old code that probably pre-dated the change to delay
emission of dllexported code until after the closing brace of the
outermost record type. Only uninstantiated default argument expressions
need to be handled now. It is enough to instantiate default argument
expressions when instantiating dllexported default ctors. This also
fixes some double-diagnostic issues in this area.
Fixes PR31500
Reviewers: rsmith
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D28274
llvm-svn: 291045
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 75 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 35 |
2 files changed, 52 insertions, 58 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 084bd4c45ed..a650621b573 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -5395,6 +5395,26 @@ static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) { } } +static void checkForMultipleExportedDefaultConstructors(Sema &S, CXXRecordDecl *Class) { + CXXConstructorDecl *LastExportedDefaultCtor = nullptr; + for (Decl *Member : Class->decls()) { + // Look for exported default constructors. + auto *CD = dyn_cast<CXXConstructorDecl>(Member); + if (!CD || !CD->isDefaultConstructor() || !CD->hasAttr<DLLExportAttr>()) + continue; + + if (LastExportedDefaultCtor) { + S.Diag(LastExportedDefaultCtor->getLocation(), + diag::err_attribute_dll_ambiguous_default_ctor) + << Class; + S.Diag(CD->getLocation(), diag::note_entity_declared_at) + << CD->getDeclName(); + return; + } + LastExportedDefaultCtor = CD; + } +} + /// \brief Check class-level dllimport/dllexport attribute. void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { Attr *ClassAttr = getDLLAttr(Class); @@ -10362,64 +10382,11 @@ void Sema::ActOnFinishCXXMemberDecls() { DelayedExceptionSpecChecks.clear(); return; } - } -} - -static void checkDefaultArgExprsForConstructors(Sema &S, CXXRecordDecl *Class) { - // Don't do anything for template patterns. - if (Class->getDescribedClassTemplate()) - return; - - CallingConv ExpectedCallingConv = S.Context.getDefaultCallingConvention( - /*IsVariadic=*/false, /*IsCXXMethod=*/true); - - CXXConstructorDecl *LastExportedDefaultCtor = nullptr; - for (Decl *Member : Class->decls()) { - auto *CD = dyn_cast<CXXConstructorDecl>(Member); - if (!CD) { - // Recurse on nested classes. - if (auto *NestedRD = dyn_cast<CXXRecordDecl>(Member)) - checkDefaultArgExprsForConstructors(S, NestedRD); - continue; - } else if (!CD->isDefaultConstructor() || !CD->hasAttr<DLLExportAttr>()) { - continue; - } - - CallingConv ActualCallingConv = - CD->getType()->getAs<FunctionProtoType>()->getCallConv(); - - // Skip default constructors with typical calling conventions and no default - // arguments. - unsigned NumParams = CD->getNumParams(); - if (ExpectedCallingConv == ActualCallingConv && NumParams == 0) - continue; - - if (LastExportedDefaultCtor) { - S.Diag(LastExportedDefaultCtor->getLocation(), - diag::err_attribute_dll_ambiguous_default_ctor) << Class; - S.Diag(CD->getLocation(), diag::note_entity_declared_at) - << CD->getDeclName(); - return; - } - LastExportedDefaultCtor = CD; - - for (unsigned I = 0; I != NumParams; ++I) { - (void)S.CheckCXXDefaultArgExpr(Class->getLocation(), CD, - CD->getParamDecl(I)); - S.DiscardCleanupsInEvaluationContext(); - } + checkForMultipleExportedDefaultConstructors(*this, Record); } } void Sema::ActOnFinishCXXNonNestedClass(Decl *D) { - auto *RD = dyn_cast<CXXRecordDecl>(D); - - // Default constructors that are annotated with __declspec(dllexport) which - // have default arguments or don't use the standard calling convention are - // wrapped with a thunk called the default constructor closure. - if (RD && Context.getTargetInfo().getCXXABI().isMicrosoft()) - checkDefaultArgExprsForConstructors(*this, RD); - referenceDLLExportedClassMethods(); } diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 3cc938106d8..f4013b82064 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3619,6 +3619,27 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New, return false; } +/// In the MS ABI, we need to instantiate default arguments of dllexported +/// default constructors along with the constructor definition. This allows IR +/// gen to emit a constructor closure which calls the default constructor with +/// its default arguments. +static void InstantiateDefaultCtorDefaultArgs(Sema &S, + CXXConstructorDecl *Ctor) { + assert(S.Context.getTargetInfo().getCXXABI().isMicrosoft() && + Ctor->isDefaultConstructor()); + unsigned NumParams = Ctor->getNumParams(); + if (NumParams == 0) + return; + DLLExportAttr *Attr = Ctor->getAttr<DLLExportAttr>(); + if (!Attr) + return; + for (unsigned I = 0; I != NumParams; ++I) { + (void)S.CheckCXXDefaultArgExpr(Attr->getLocation(), Ctor, + Ctor->getParamDecl(I)); + S.DiscardCleanupsInEvaluationContext(); + } +} + /// \brief Instantiate the definition of the given function from its /// template. /// @@ -3796,11 +3817,17 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, TemplateArgs)) return; - // If this is a constructor, instantiate the member initializers. - if (const CXXConstructorDecl *Ctor = - dyn_cast<CXXConstructorDecl>(PatternDecl)) { - InstantiateMemInitializers(cast<CXXConstructorDecl>(Function), Ctor, + if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Function)) { + // If this is a constructor, instantiate the member initializers. + InstantiateMemInitializers(Ctor, cast<CXXConstructorDecl>(PatternDecl), TemplateArgs); + + // If this is an MS ABI dllexport default constructor, instantiate any + // default arguments. + if (Context.getTargetInfo().getCXXABI().isMicrosoft() && + Ctor->isDefaultConstructor()) { + InstantiateDefaultCtorDefaultArgs(*this, Ctor); + } } // Instantiate the function body. |