diff options
author | Hal Finkel <hfinkel@anl.gov> | 2014-09-26 05:04:30 +0000 |
---|---|---|
committer | Hal Finkel <hfinkel@anl.gov> | 2014-09-26 05:04:30 +0000 |
commit | ee90a223ead9d1389e0538401e8c88cffa4e7507 (patch) | |
tree | 69f450c880a58dd8131d04463afd90fd666470d0 /clang/lib/Sema | |
parent | ec44e4d05382e668ac84467a1ed99f398cd4a170 (diff) | |
download | bcm5719-llvm-ee90a223ead9d1389e0538401e8c88cffa4e7507.tar.gz bcm5719-llvm-ee90a223ead9d1389e0538401e8c88cffa4e7507.zip |
Support the assume_aligned function attribute
In addition to __builtin_assume_aligned, GCC also supports an assume_aligned
attribute which specifies the alignment (and optional offset) of a function's
return value. Here we implement support for the assume_aligned attribute by making
use of the @llvm.assume intrinsic.
llvm-svn: 218500
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 84 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 29 |
3 files changed, 106 insertions, 9 deletions
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 5ea862cf88a..2cf25feae2e 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -877,7 +877,7 @@ static void CheckNonNullArguments(Sema &S, if (!NonNull->args_size()) { // Easy case: all pointer arguments are nonnull. for (const auto *Arg : Args) - if (S.isValidNonNullAttrType(Arg->getType())) + if (S.isValidPointerAttrType(Arg->getType())) CheckNonNullArgument(S, Arg, CallSiteLoc); return; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index e3bb2c993e9..227ceaaee29 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -29,6 +29,7 @@ #include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/MathExtras.h" using namespace clang; using namespace sema; @@ -1125,11 +1126,16 @@ static void handleIBOutletCollection(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } -bool Sema::isValidNonNullAttrType(QualType T) { - T = T.getNonReferenceType(); +bool Sema::isValidPointerAttrType(QualType T, bool RefOkay) { + if (RefOkay) { + if (T->isReferenceType()) + return true; + } else { + T = T.getNonReferenceType(); + } - // The nonnull attribute can be applied to a transparent union that - // contains a pointer type. + // The nonnull attribute, and other similar attributes, can be applied to a + // transparent union that contains a pointer type. if (const RecordType *UT = T->getAsUnionType()) { if (UT && UT->getDecl()->hasAttr<TransparentUnionAttr>()) { RecordDecl *UD = UT->getDecl(); @@ -1146,13 +1152,13 @@ bool Sema::isValidNonNullAttrType(QualType T) { static bool attrNonNullArgCheck(Sema &S, QualType T, const AttributeList &Attr, SourceRange AttrParmRange, - SourceRange NonNullTypeRange, + SourceRange TypeRange, bool isReturnValue = false) { - if (!S.isValidNonNullAttrType(T)) { + if (!S.isValidPointerAttrType(T)) { S.Diag(Attr.getLoc(), isReturnValue ? diag::warn_attribute_return_pointers_only : diag::warn_attribute_pointers_only) - << Attr.getName() << AttrParmRange << NonNullTypeRange; + << Attr.getName() << AttrParmRange << TypeRange; return false; } return true; @@ -1186,7 +1192,7 @@ static void handleNonNullAttr(Sema &S, Decl *D, const AttributeList &Attr) { for (unsigned I = 0, E = getFunctionOrMethodNumParams(D); I != E && !AnyPointers; ++I) { QualType T = getFunctionOrMethodParamType(D, I); - if (T->isDependentType() || S.isValidNonNullAttrType(T)) + if (T->isDependentType() || S.isValidPointerAttrType(T)) AnyPointers = true; } @@ -1237,6 +1243,65 @@ static void handleReturnsNonNullAttr(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } +static void handleAssumeAlignedAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + Expr *E = Attr.getArgAsExpr(0), + *OE = Attr.getNumArgs() > 1 ? Attr.getArgAsExpr(1) : nullptr; + S.AddAssumeAlignedAttr(Attr.getRange(), D, E, OE, + Attr.getAttributeSpellingListIndex()); +} + +void Sema::AddAssumeAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, + Expr *OE, unsigned SpellingListIndex) { + QualType ResultType = getFunctionOrMethodResultType(D); + SourceRange SR = getFunctionOrMethodResultSourceRange(D); + + AssumeAlignedAttr TmpAttr(AttrRange, Context, E, OE, SpellingListIndex); + SourceLocation AttrLoc = AttrRange.getBegin(); + + if (!isValidPointerAttrType(ResultType, /* RefOkay */ true)) { + Diag(AttrLoc, diag::warn_attribute_return_pointers_refs_only) + << &TmpAttr << AttrRange << SR; + return; + } + + if (!E->isValueDependent()) { + llvm::APSInt I(64); + if (!E->isIntegerConstantExpr(I, Context)) { + if (OE) + Diag(AttrLoc, diag::err_attribute_argument_n_type) + << &TmpAttr << 1 << AANT_ArgumentIntegerConstant + << E->getSourceRange(); + else + Diag(AttrLoc, diag::err_attribute_argument_type) + << &TmpAttr << AANT_ArgumentIntegerConstant + << E->getSourceRange(); + return; + } + + if (!I.isPowerOf2()) { + Diag(AttrLoc, diag::err_alignment_not_power_of_two) + << E->getSourceRange(); + return; + } + } + + if (OE) { + if (!OE->isValueDependent()) { + llvm::APSInt I(64); + if (!OE->isIntegerConstantExpr(I, Context)) { + Diag(AttrLoc, diag::err_attribute_argument_n_type) + << &TmpAttr << 2 << AANT_ArgumentIntegerConstant + << OE->getSourceRange(); + return; + } + } + } + + D->addAttr(::new (Context) + AssumeAlignedAttr(AttrRange, Context, E, OE, SpellingListIndex)); +} + static void handleOwnershipAttr(Sema &S, Decl *D, const AttributeList &AL) { // This attribute must be applied to a function declaration. The first // argument to the attribute must be an identifier, the name of the resource, @@ -4212,6 +4277,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_ReturnsNonNull: handleReturnsNonNullAttr(S, D, Attr); break; + case AttributeList::AT_AssumeAligned: + handleAssumeAlignedAttr(S, D, Attr); + break; case AttributeList::AT_Overloadable: handleSimpleAttribute<OverloadableAttr>(S, D, Attr); break; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 62a3e11ac9a..9d194a3ad14 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -129,6 +129,29 @@ static void instantiateDependentAlignedAttr( } } +static void instantiateDependentAssumeAlignedAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const AssumeAlignedAttr *Aligned, Decl *New) { + // The alignment expression is a constant expression. + EnterExpressionEvaluationContext Unevaluated(S, Sema::ConstantEvaluated); + + Expr *E, *OE = nullptr; + ExprResult Result = S.SubstExpr(Aligned->getAlignment(), TemplateArgs); + if (Result.isInvalid()) + return; + E = Result.getAs<Expr>(); + + if (Aligned->getOffset()) { + Result = S.SubstExpr(Aligned->getOffset(), TemplateArgs); + if (Result.isInvalid()) + return; + OE = Result.getAs<Expr>(); + } + + S.AddAssumeAlignedAttr(Aligned->getLocation(), New, E, OE, + Aligned->getSpellingListIndex()); +} + static void instantiateDependentEnableIfAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, const EnableIfAttr *A, const Decl *Tmpl, Decl *New) { @@ -176,6 +199,12 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, continue; } + const AssumeAlignedAttr *AssumeAligned = dyn_cast<AssumeAlignedAttr>(TmplAttr); + if (AssumeAligned) { + instantiateDependentAssumeAlignedAttr(*this, TemplateArgs, AssumeAligned, New); + continue; + } + const EnableIfAttr *EnableIf = dyn_cast<EnableIfAttr>(TmplAttr); if (EnableIf && EnableIf->getCond()->isValueDependent()) { instantiateDependentEnableIfAttr(*this, TemplateArgs, EnableIf, Tmpl, |