diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 19 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 55 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 17 |
3 files changed, 91 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 3db23f2bcb7..b40fa9d93d4 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1743,6 +1743,25 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, AI->getArgNo() + 1, llvm::Attribute::NonNull)); } + + const auto *AVAttr = PVD->getAttr<AlignValueAttr>(); + if (!AVAttr) + if (const auto *TOTy = dyn_cast<TypedefType>(OTy)) + AVAttr = TOTy->getDecl()->getAttr<AlignValueAttr>(); + if (AVAttr) { + llvm::Value *AlignmentValue = + EmitScalarExpr(AVAttr->getAlignment()); + llvm::ConstantInt *AlignmentCI = + cast<llvm::ConstantInt>(AlignmentValue); + unsigned Alignment = + std::min((unsigned) AlignmentCI->getZExtValue(), + +llvm::Value::MaximumAlignment); + + llvm::AttrBuilder Attrs; + Attrs.addAlignmentAttr(Alignment); + AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), + AI->getArgNo() + 1, Attrs)); + } } if (Arg->getType().isRestrictQualified()) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 227ceaaee29..406e511651f 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2757,6 +2757,58 @@ static void handleAnnotateAttr(Sema &S, Decl *D, const AttributeList &Attr) { Attr.getAttributeSpellingListIndex())); } +static void handleAlignValueAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + S.AddAlignValueAttr(Attr.getRange(), D, Attr.getArgAsExpr(0), + Attr.getAttributeSpellingListIndex()); +} + +void Sema::AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E, + unsigned SpellingListIndex) { + AlignValueAttr TmpAttr(AttrRange, Context, E, SpellingListIndex); + SourceLocation AttrLoc = AttrRange.getBegin(); + + QualType T; + if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) + T = TD->getUnderlyingType(); + else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) + T = VD->getType(); + else + llvm_unreachable("Unknown decl type for align_value"); + + if (!T->isDependentType() && !T->isAnyPointerType() && + !T->isReferenceType() && !T->isMemberPointerType()) { + Diag(AttrLoc, diag::warn_attribute_pointer_or_reference_only) + << &TmpAttr /*TmpAttr.getName()*/ << T << D->getSourceRange(); + return; + } + + if (!E->isValueDependent()) { + llvm::APSInt Alignment(32); + ExprResult ICE + = VerifyIntegerConstantExpression(E, &Alignment, + diag::err_align_value_attribute_argument_not_int, + /*AllowFold*/ false); + if (ICE.isInvalid()) + return; + + if (!Alignment.isPowerOf2()) { + Diag(AttrLoc, diag::err_alignment_not_power_of_two) + << E->getSourceRange(); + return; + } + + D->addAttr(::new (Context) + AlignValueAttr(AttrRange, Context, ICE.get(), + SpellingListIndex)); + return; + } + + // Save dependent expressions in the AST to be instantiated. + D->addAttr(::new (Context) AlignValueAttr(TmpAttr)); + return; +} + static void handleAlignedAttr(Sema &S, Decl *D, const AttributeList &Attr) { // check the attribute arguments. if (Attr.getNumArgs() > 1) { @@ -4181,6 +4233,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_Aligned: handleAlignedAttr(S, D, Attr); break; + case AttributeList::AT_AlignValue: + handleAlignValueAttr(S, D, Attr); + break; case AttributeList::AT_AlwaysInline: handleAlwaysInlineAttr(S, D, Attr); break; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 9d194a3ad14..dce8ca4c8a9 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -152,6 +152,17 @@ static void instantiateDependentAssumeAlignedAttr( Aligned->getSpellingListIndex()); } +static void instantiateDependentAlignValueAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const AlignValueAttr *Aligned, Decl *New) { + // The alignment expression is a constant expression. + EnterExpressionEvaluationContext Unevaluated(S, Sema::ConstantEvaluated); + ExprResult Result = S.SubstExpr(Aligned->getAlignment(), TemplateArgs); + if (!Result.isInvalid()) + S.AddAlignValueAttr(Aligned->getLocation(), New, Result.getAs<Expr>(), + Aligned->getSpellingListIndex()); +} + static void instantiateDependentEnableIfAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, const EnableIfAttr *A, const Decl *Tmpl, Decl *New) { @@ -205,6 +216,12 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, continue; } + const AlignValueAttr *AlignValue = dyn_cast<AlignValueAttr>(TmplAttr); + if (AlignValue) { + instantiateDependentAlignValueAttr(*this, TemplateArgs, AlignValue, New); + continue; + } + const EnableIfAttr *EnableIf = dyn_cast<EnableIfAttr>(TmplAttr); if (EnableIf && EnableIf->getCond()->isValueDependent()) { instantiateDependentEnableIfAttr(*this, TemplateArgs, EnableIf, Tmpl, |