Skip to content

Commit 9711118

Browse files
committed
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.
1 parent a46f59a commit 9711118

File tree

5 files changed

+35
-30
lines changed

5 files changed

+35
-30
lines changed

clang/include/clang/Sema/Sema.h

+8-6
Original file line numberDiff line numberDiff line change
@@ -4296,10 +4296,11 @@ class Sema final {
42964296
/// Valid types should not have multiple attributes with different CCs.
42974297
const AttributedType *getCallingConvAttributedType(QualType T) const;
42984298

4299-
/// Stmt attributes - this routine is the top level dispatcher.
4300-
StmtResult ProcessStmtAttributes(Stmt *Stmt,
4301-
const ParsedAttributesView &Attrs,
4302-
SourceRange Range);
4299+
/// Process the attributes before creating an attributed statement. Returns
4300+
/// the semantic attributes that have been processed.
4301+
void ProcessStmtAttributes(Stmt *Stmt,
4302+
const ParsedAttributesWithRange &InAttrs,
4303+
SmallVectorImpl<const Attr *> &OutAttrs);
43034304

43044305
void WarnConflictingTypedMethods(ObjCMethodDecl *Method,
43054306
ObjCMethodDecl *MethodDecl,
@@ -4638,8 +4639,9 @@ class Sema final {
46384639
StmtResult ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
46394640
SourceLocation ColonLoc, Stmt *SubStmt);
46404641

4641-
StmtResult ActOnAttributedStmt(SourceLocation AttrLoc,
4642-
ArrayRef<const Attr*> Attrs,
4642+
StmtResult BuildAttributedStmt(SourceLocation AttrsLoc,
4643+
ArrayRef<const Attr *> Attrs, Stmt *SubStmt);
4644+
StmtResult ActOnAttributedStmt(const ParsedAttributesWithRange &AttrList,
46434645
Stmt *SubStmt);
46444646

46454647
class ConditionResult;

clang/lib/Parse/ParseStmt.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts,
120120
if (Attrs.empty() || Res.isInvalid())
121121
return Res;
122122

123-
return Actions.ProcessStmtAttributes(Res.get(), Attrs, Attrs.Range);
123+
return Actions.ActOnAttributedStmt(Attrs, Res.get());
124124
}
125125

126126
namespace {
@@ -657,8 +657,7 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs,
657657
SubStmt = ParseStatementOrDeclarationAfterAttributes(Stmts, StmtCtx,
658658
nullptr, TempAttrs);
659659
if (!TempAttrs.empty() && !SubStmt.isInvalid())
660-
SubStmt = Actions.ProcessStmtAttributes(SubStmt.get(), TempAttrs,
661-
TempAttrs.Range);
660+
SubStmt = Actions.ActOnAttributedStmt(TempAttrs, SubStmt.get());
662661
} else {
663662
Diag(Tok, diag::err_expected_after) << "__attribute__" << tok::semi;
664663
}
@@ -1144,7 +1143,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
11441143
ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
11451144
R = handleExprStmt(Res, SubStmtCtx);
11461145
if (R.isUsable())
1147-
R = Actions.ProcessStmtAttributes(R.get(), attrs, attrs.Range);
1146+
R = Actions.ActOnAttributedStmt(attrs, R.get());
11481147
}
11491148
}
11501149

clang/lib/Sema/SemaStmt.cpp

+15-5
Original file line numberDiff line numberDiff line change
@@ -555,12 +555,22 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
555555
return LS;
556556
}
557557

558-
StmtResult Sema::ActOnAttributedStmt(SourceLocation AttrLoc,
559-
ArrayRef<const Attr*> Attrs,
558+
StmtResult Sema::BuildAttributedStmt(SourceLocation AttrsLoc,
559+
ArrayRef<const Attr *> Attrs,
560560
Stmt *SubStmt) {
561-
// Fill in the declaration and return it.
562-
AttributedStmt *LS = AttributedStmt::Create(Context, AttrLoc, Attrs, SubStmt);
563-
return LS;
561+
return AttributedStmt::Create(Context, AttrsLoc, Attrs, SubStmt);
562+
}
563+
564+
StmtResult Sema::ActOnAttributedStmt(const ParsedAttributesWithRange &Attrs,
565+
Stmt *SubStmt) {
566+
SmallVector<const Attr *, 1> SemanticAttrs;
567+
ProcessStmtAttributes(SubStmt, Attrs, SemanticAttrs);
568+
if (!SemanticAttrs.empty())
569+
return BuildAttributedStmt(Attrs.Range.getBegin(), SemanticAttrs, SubStmt);
570+
// If none of the attributes applied, that's fine, we can recover by
571+
// returning the substatement directly instead of making an AttributedStmt
572+
// with no attributes on it.
573+
return SubStmt;
564574
}
565575

566576
namespace {

clang/lib/Sema/SemaStmtAttr.cpp

+7-13
Original file line numberDiff line numberDiff line change
@@ -413,19 +413,13 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A,
413413
}
414414
}
415415

416-
StmtResult Sema::ProcessStmtAttributes(Stmt *S,
417-
const ParsedAttributesView &AttrList,
418-
SourceRange Range) {
419-
SmallVector<const Attr*, 8> Attrs;
420-
for (const ParsedAttr &AL : AttrList) {
421-
if (Attr *a = ProcessStmtAttribute(*this, S, AL, Range))
422-
Attrs.push_back(a);
416+
void Sema::ProcessStmtAttributes(Stmt *S,
417+
const ParsedAttributesWithRange &InAttrs,
418+
SmallVectorImpl<const Attr *> &OutAttrs) {
419+
for (const ParsedAttr &AL : InAttrs) {
420+
if (const Attr *A = ProcessStmtAttribute(*this, S, AL, InAttrs.Range))
421+
OutAttrs.push_back(A);
423422
}
424423

425-
CheckForIncompatibleAttributes(*this, Attrs);
426-
427-
if (Attrs.empty())
428-
return S;
429-
430-
return ActOnAttributedStmt(Range.getBegin(), Attrs, S);
424+
CheckForIncompatibleAttributes(*this, OutAttrs);
431425
}

clang/lib/Sema/TreeTransform.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -1311,9 +1311,9 @@ class TreeTransform {
13111311
/// By default, performs semantic analysis to build the new statement.
13121312
/// Subclasses may override this routine to provide different behavior.
13131313
StmtResult RebuildAttributedStmt(SourceLocation AttrLoc,
1314-
ArrayRef<const Attr*> Attrs,
1314+
ArrayRef<const Attr *> Attrs,
13151315
Stmt *SubStmt) {
1316-
return SemaRef.ActOnAttributedStmt(AttrLoc, Attrs, SubStmt);
1316+
return SemaRef.BuildAttributedStmt(AttrLoc, Attrs, SubStmt);
13171317
}
13181318

13191319
/// Build a new "if" statement.

0 commit comments

Comments
 (0)