forked from OSchip/llvm-project
Rework the way statement attributes are processed; NFC
This changes our approach to processing statement attributes to be more similar to how we process declaration attributes. Namely, ActOnAttributedStmt() now calls ProcessStmtAttributes() instead of vice-versa, and there is now an interface split between building an attributed statement where you already have a list of semantic attributes and building an attributed statement with attributes from the parser. This should make it easier to support statement attributes that are dependent on a template. In that case, you would add a TransformFooAttr() function in TreeTransform.h to perform the semantic checking (morally similar to how Sema::InstantiateAttrs() already works for declaration attributes) when transforming the semantic attribute at instantiation time.
This commit is contained in:
parent
a46f59a747
commit
9711118d2e
|
@ -4296,10 +4296,11 @@ public:
|
|||
/// Valid types should not have multiple attributes with different CCs.
|
||||
const AttributedType *getCallingConvAttributedType(QualType T) const;
|
||||
|
||||
/// Stmt attributes - this routine is the top level dispatcher.
|
||||
StmtResult ProcessStmtAttributes(Stmt *Stmt,
|
||||
const ParsedAttributesView &Attrs,
|
||||
SourceRange Range);
|
||||
/// Process the attributes before creating an attributed statement. Returns
|
||||
/// the semantic attributes that have been processed.
|
||||
void ProcessStmtAttributes(Stmt *Stmt,
|
||||
const ParsedAttributesWithRange &InAttrs,
|
||||
SmallVectorImpl<const Attr *> &OutAttrs);
|
||||
|
||||
void WarnConflictingTypedMethods(ObjCMethodDecl *Method,
|
||||
ObjCMethodDecl *MethodDecl,
|
||||
|
@ -4638,8 +4639,9 @@ public:
|
|||
StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
|
||||
SourceLocation ColonLoc, Stmt *SubStmt);
|
||||
|
||||
StmtResult ActOnAttributedStmt(SourceLocation AttrLoc,
|
||||
ArrayRef<const Attr*> Attrs,
|
||||
StmtResult BuildAttributedStmt(SourceLocation AttrsLoc,
|
||||
ArrayRef<const Attr *> Attrs, Stmt *SubStmt);
|
||||
StmtResult ActOnAttributedStmt(const ParsedAttributesWithRange &AttrList,
|
||||
Stmt *SubStmt);
|
||||
|
||||
class ConditionResult;
|
||||
|
|
|
@ -120,7 +120,7 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts,
|
|||
if (Attrs.empty() || Res.isInvalid())
|
||||
return Res;
|
||||
|
||||
return Actions.ProcessStmtAttributes(Res.get(), Attrs, Attrs.Range);
|
||||
return Actions.ActOnAttributedStmt(Attrs, Res.get());
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -657,8 +657,7 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs,
|
|||
SubStmt = ParseStatementOrDeclarationAfterAttributes(Stmts, StmtCtx,
|
||||
nullptr, TempAttrs);
|
||||
if (!TempAttrs.empty() && !SubStmt.isInvalid())
|
||||
SubStmt = Actions.ProcessStmtAttributes(SubStmt.get(), TempAttrs,
|
||||
TempAttrs.Range);
|
||||
SubStmt = Actions.ActOnAttributedStmt(TempAttrs, SubStmt.get());
|
||||
} else {
|
||||
Diag(Tok, diag::err_expected_after) << "__attribute__" << tok::semi;
|
||||
}
|
||||
|
@ -1144,7 +1143,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
|
|||
ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
|
||||
R = handleExprStmt(Res, SubStmtCtx);
|
||||
if (R.isUsable())
|
||||
R = Actions.ProcessStmtAttributes(R.get(), attrs, attrs.Range);
|
||||
R = Actions.ActOnAttributedStmt(attrs, R.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -555,12 +555,22 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
|
|||
return LS;
|
||||
}
|
||||
|
||||
StmtResult Sema::ActOnAttributedStmt(SourceLocation AttrLoc,
|
||||
ArrayRef<const Attr*> Attrs,
|
||||
StmtResult Sema::BuildAttributedStmt(SourceLocation AttrsLoc,
|
||||
ArrayRef<const Attr *> Attrs,
|
||||
Stmt *SubStmt) {
|
||||
// Fill in the declaration and return it.
|
||||
AttributedStmt *LS = AttributedStmt::Create(Context, AttrLoc, Attrs, SubStmt);
|
||||
return LS;
|
||||
return AttributedStmt::Create(Context, AttrsLoc, Attrs, SubStmt);
|
||||
}
|
||||
|
||||
StmtResult Sema::ActOnAttributedStmt(const ParsedAttributesWithRange &Attrs,
|
||||
Stmt *SubStmt) {
|
||||
SmallVector<const Attr *, 1> SemanticAttrs;
|
||||
ProcessStmtAttributes(SubStmt, Attrs, SemanticAttrs);
|
||||
if (!SemanticAttrs.empty())
|
||||
return BuildAttributedStmt(Attrs.Range.getBegin(), SemanticAttrs, SubStmt);
|
||||
// If none of the attributes applied, that's fine, we can recover by
|
||||
// returning the substatement directly instead of making an AttributedStmt
|
||||
// with no attributes on it.
|
||||
return SubStmt;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
|
|
@ -413,19 +413,13 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
|
|||
}
|
||||
}
|
||||
|
||||
StmtResult Sema::ProcessStmtAttributes(Stmt *S,
|
||||
const ParsedAttributesView &AttrList,
|
||||
SourceRange Range) {
|
||||
SmallVector<const Attr*, 8> Attrs;
|
||||
for (const ParsedAttr &AL : AttrList) {
|
||||
if (Attr *a = ProcessStmtAttribute(*this, S, AL, Range))
|
||||
Attrs.push_back(a);
|
||||
void Sema::ProcessStmtAttributes(Stmt *S,
|
||||
const ParsedAttributesWithRange &InAttrs,
|
||||
SmallVectorImpl<const Attr *> &OutAttrs) {
|
||||
for (const ParsedAttr &AL : InAttrs) {
|
||||
if (const Attr *A = ProcessStmtAttribute(*this, S, AL, InAttrs.Range))
|
||||
OutAttrs.push_back(A);
|
||||
}
|
||||
|
||||
CheckForIncompatibleAttributes(*this, Attrs);
|
||||
|
||||
if (Attrs.empty())
|
||||
return S;
|
||||
|
||||
return ActOnAttributedStmt(Range.getBegin(), Attrs, S);
|
||||
CheckForIncompatibleAttributes(*this, OutAttrs);
|
||||
}
|
||||
|
|
|
@ -1311,9 +1311,9 @@ public:
|
|||
/// By default, performs semantic analysis to build the new statement.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
StmtResult RebuildAttributedStmt(SourceLocation AttrLoc,
|
||||
ArrayRef<const Attr*> Attrs,
|
||||
ArrayRef<const Attr *> Attrs,
|
||||
Stmt *SubStmt) {
|
||||
return SemaRef.ActOnAttributedStmt(AttrLoc, Attrs, SubStmt);
|
||||
return SemaRef.BuildAttributedStmt(AttrLoc, Attrs, SubStmt);
|
||||
}
|
||||
|
||||
/// Build a new "if" statement.
|
||||
|
|
Loading…
Reference in New Issue