diff options
author | Reid Kleckner <reid@kleckner.net> | 2015-03-17 19:00:50 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2015-03-17 19:00:50 +0000 |
commit | bba3cb95cc548e8700eaf00f74268c1cfcef2fa8 (patch) | |
tree | 7ef4d47f50ac517278043a5b855e70d1c8427257 /clang/lib/Sema/SemaDeclCXX.cpp | |
parent | 426025222228658060bba5aaea98a1bc1b090cb0 (diff) | |
download | bcm5719-llvm-bba3cb95cc548e8700eaf00f74268c1cfcef2fa8.tar.gz bcm5719-llvm-bba3cb95cc548e8700eaf00f74268c1cfcef2fa8.zip |
MS ABI: Delay default constructor closure checking until the outermost class scope ends
Previously, we would error out on this code because the default argument
wasn't parsed until the end of Outer:
struct __declspec(dllexport) Outer {
struct __declspec(dllexport) Inner {
Inner(void *p = 0);
};
};
Now we do the checking on the closing brace of Outer instead of Inner.
llvm-svn: 232519
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 45ba685d118..4e64595e114 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -9421,6 +9421,44 @@ void Sema::ActOnFinishCXXMemberDecls() { } } +static void getDefaultArgExprsForConstructors(Sema &S, CXXRecordDecl *Class) { + // Don't do anything for template patterns. + if (Class->getDescribedClassTemplate()) + return; + + for (Decl *Member : Class->decls()) { + auto *CD = dyn_cast<CXXConstructorDecl>(Member); + if (!CD) { + // Recurse on nested classes. + if (auto *NestedRD = dyn_cast<CXXRecordDecl>(Member)) + getDefaultArgExprsForConstructors(S, NestedRD); + continue; + } else if (!CD->isDefaultConstructor() || !CD->hasAttr<DLLExportAttr>()) { + continue; + } + + for (unsigned I = 0, E = CD->getNumParams(); I != E; ++I) { + // Skip any default arguments that we've already instantiated. + if (S.Context.getDefaultArgExprForConstructor(CD, I)) + continue; + + Expr *DefaultArg = S.BuildCXXDefaultArgExpr(Class->getLocation(), CD, + CD->getParamDecl(I)).get(); + S.Context.addDefaultArgExprForConstructor(CD, I, DefaultArg); + } + } +} + +void Sema::ActOnFinishCXXMethodDefs(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()) + getDefaultArgExprsForConstructors(*this, RD); +} + void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, CXXDestructorDecl *Destructor) { assert(getLangOpts().CPlusPlus11 && |