diff options
Diffstat (limited to 'clang/lib/Sema/SemaStmtAttr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaStmtAttr.cpp | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index 3d91893b4065..e9d3c755eb23 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/EvaluatedExprVisitor.h" #include "clang/Sema/SemaInternal.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/SourceManager.h" @@ -170,6 +171,44 @@ static Attr *handleLoopHintAttr(Sema &S, Stmt *St, const ParsedAttr &A, return LoopHintAttr::CreateImplicit(S.Context, Option, State, ValueExpr, A); } +namespace { +class CallExprFinder : public ConstEvaluatedExprVisitor<CallExprFinder> { + bool FoundCallExpr = false; + +public: + typedef ConstEvaluatedExprVisitor<CallExprFinder> Inherited; + + CallExprFinder(Sema &S, const Stmt *St) : Inherited(S.Context) { Visit(St); } + + bool foundCallExpr() { return FoundCallExpr; } + + void VisitCallExpr(const CallExpr *E) { FoundCallExpr = true; } + + void Visit(const Stmt *St) { + if (!St) + return; + ConstEvaluatedExprVisitor<CallExprFinder>::Visit(St); + } +}; +} // namespace + +static Attr *handleNoMergeAttr(Sema &S, Stmt *St, const ParsedAttr &A, + SourceRange Range) { + NoMergeAttr NMA(S.Context, A); + if (S.CheckAttrNoArgs(A)) + return nullptr; + + CallExprFinder CEF(S, St); + + if (!CEF.foundCallExpr()) { + S.Diag(St->getBeginLoc(), diag::warn_nomerge_attribute_ignored_in_stmt) + << NMA.getSpelling(); + return nullptr; + } + + return ::new (S.Context) NoMergeAttr(S.Context, A); +} + static void CheckForIncompatibleAttributes(Sema &S, const SmallVectorImpl<const Attr *> &Attrs) { @@ -335,6 +374,8 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A, return handleOpenCLUnrollHint(S, St, A, Range); case ParsedAttr::AT_Suppress: return handleSuppressAttr(S, St, A, Range); + case ParsedAttr::AT_NoMerge: + return handleNoMergeAttr(S, St, A, Range); default: // if we're here, then we parsed a known attribute, but didn't recognize // it as a statement attribute => it is declaration attribute |