diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-02-22 08:32:16 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-02-22 08:32:16 +0000 |
commit | f6565a9f7318b1ca6ea9510003dde7b89696daab (patch) | |
tree | 86b86d9f7d52395d08d9bed8250c6ab2ce7e7d46 /lib/Sema | |
parent | 745af1c348191bf31cfcd3ae61443a0321ec2d75 (diff) |
Handle alignas(foo...) pack expansions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175875 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 44 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 86 |
2 files changed, 88 insertions, 42 deletions
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 1142e0dd2d..8e2bac6ed0 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -3315,27 +3315,28 @@ static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - // FIXME: The C++11 version of this attribute should error out when it is - // used to specify a weaker alignment, rather than being silently - // ignored. This constraint cannot be applied until we have seen - // all the attributes which apply to the variable. - if (Attr.getNumArgs() == 0) { D->addAttr(::new (S.Context) AlignedAttr(Attr.getRange(), S.Context, true, 0, Attr.getAttributeSpellingListIndex())); return; } - S.AddAlignedAttr(Attr.getRange(), D, Attr.getArg(0), - Attr.getAttributeSpellingListIndex()); -} + Expr *E = Attr.getArg(0); + if (Attr.isPackExpansion() && !E->containsUnexpandedParameterPack()) { + S.Diag(Attr.getEllipsisLoc(), + diag::err_pack_expansion_without_parameter_packs); + return; + } -void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, - unsigned SpellingListIndex) { - // FIXME: Handle pack-expansions here. - if (DiagnoseUnexpandedParameterPack(E)) + if (!Attr.isPackExpansion() && S.DiagnoseUnexpandedParameterPack(E)) return; + S.AddAlignedAttr(Attr.getRange(), D, E, Attr.getAttributeSpellingListIndex(), + Attr.isPackExpansion()); +} + +void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, + unsigned SpellingListIndex, bool IsPackExpansion) { AlignedAttr TmpAttr(AttrRange, Context, true, E, SpellingListIndex); SourceLocation AttrLoc = AttrRange.getBegin(); @@ -3379,7 +3380,9 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, if (E->isTypeDependent() || E->isValueDependent()) { // Save dependent expressions in the AST to be instantiated. - D->addAttr(::new (Context) AlignedAttr(TmpAttr)); + AlignedAttr *AA = ::new (Context) AlignedAttr(TmpAttr); + AA->setPackExpansion(IsPackExpansion); + D->addAttr(AA); return; } @@ -3414,17 +3417,20 @@ void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, } } - D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, true, - ICE.take(), SpellingListIndex)); + AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, true, + ICE.take(), SpellingListIndex); + AA->setPackExpansion(IsPackExpansion); + D->addAttr(AA); } void Sema::AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *TS, - unsigned SpellingListIndex) { + unsigned SpellingListIndex, bool IsPackExpansion) { // FIXME: Cache the number on the Attr object if non-dependent? // FIXME: Perform checking of type validity - D->addAttr(::new (Context) AlignedAttr(AttrRange, Context, false, TS, - SpellingListIndex)); - return; + AlignedAttr *AA = ::new (Context) AlignedAttr(AttrRange, Context, false, TS, + SpellingListIndex); + AA->setPackExpansion(IsPackExpansion); + D->addAttr(AA); } void Sema::CheckAlignasUnderalignment(Decl *D) { diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index defa968475..a829070b2f 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -60,6 +60,64 @@ bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl, // Include attribute instantiation code. #include "clang/Sema/AttrTemplateInstantiate.inc" +static void instantiateDependentAlignedAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const AlignedAttr *Aligned, Decl *New, bool IsPackExpansion) { + if (Aligned->isAlignmentExpr()) { + // The alignment expression is a constant expression. + EnterExpressionEvaluationContext Unevaluated(S, Sema::ConstantEvaluated); + ExprResult Result = S.SubstExpr(Aligned->getAlignmentExpr(), TemplateArgs); + if (!Result.isInvalid()) + S.AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>(), + Aligned->getSpellingListIndex(), IsPackExpansion); + } else { + TypeSourceInfo *Result = S.SubstType(Aligned->getAlignmentType(), + TemplateArgs, Aligned->getLocation(), + DeclarationName()); + if (Result) + S.AddAlignedAttr(Aligned->getLocation(), New, Result, + Aligned->getSpellingListIndex(), IsPackExpansion); + } +} + +static void instantiateDependentAlignedAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const AlignedAttr *Aligned, Decl *New) { + if (!Aligned->isPackExpansion()) { + instantiateDependentAlignedAttr(S, TemplateArgs, Aligned, New, false); + return; + } + + SmallVector<UnexpandedParameterPack, 2> Unexpanded; + if (Aligned->isAlignmentExpr()) + S.collectUnexpandedParameterPacks(Aligned->getAlignmentExpr(), + Unexpanded); + else + S.collectUnexpandedParameterPacks(Aligned->getAlignmentType()->getTypeLoc(), + Unexpanded); + assert(!Unexpanded.empty() && "Pack expansion without parameter packs?"); + + // Determine whether we can expand this attribute pack yet. + bool Expand = true, RetainExpansion = false; + Optional<unsigned> NumExpansions; + // FIXME: Use the actual location of the ellipsis. + SourceLocation EllipsisLoc = Aligned->getLocation(); + if (S.CheckParameterPacksForExpansion(EllipsisLoc, Aligned->getRange(), + Unexpanded, TemplateArgs, Expand, + RetainExpansion, NumExpansions)) + return; + + if (!Expand) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, -1); + instantiateDependentAlignedAttr(S, TemplateArgs, Aligned, New, true); + } else { + for (unsigned I = 0; I != *NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, I); + instantiateDependentAlignedAttr(S, TemplateArgs, Aligned, New, false); + } + } +} + void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, const Decl *Tmpl, Decl *New, LateInstantiatedAttrVec *LateAttrs, @@ -69,31 +127,13 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, const Attr *TmplAttr = *i; // FIXME: This should be generalized to more than just the AlignedAttr. - if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) { - if (Aligned->isAlignmentDependent()) { - if (Aligned->isAlignmentExpr()) { - // The alignment expression is a constant expression. - EnterExpressionEvaluationContext Unevaluated(*this, - Sema::ConstantEvaluated); - - ExprResult Result = SubstExpr(Aligned->getAlignmentExpr(), - TemplateArgs); - if (!Result.isInvalid()) - AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>(), - Aligned->getSpellingListIndex()); - } else { - TypeSourceInfo *Result = SubstType(Aligned->getAlignmentType(), - TemplateArgs, - Aligned->getLocation(), - DeclarationName()); - if (Result) - AddAlignedAttr(Aligned->getLocation(), New, Result, - Aligned->getSpellingListIndex()); - } - continue; - } + const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr); + if (Aligned && Aligned->isAlignmentDependent()) { + instantiateDependentAlignedAttr(*this, TemplateArgs, Aligned, New); + continue; } + assert(!TmplAttr->isPackExpansion()); if (TmplAttr->isLateParsed() && LateAttrs) { // Late parsed attributes must be instantiated and attached after the // enclosing class has been instantiated. See Sema::InstantiateClass. |