Skip to content

Commit df1e102

Browse files
committed
[OpenACC] implement AST/Sema for 'routine' construct with argument
The 'routine' construct has two forms, one which takes the name of a function that it applies to, and another where it implicitly figures it out based on the next declaration. This patch implements the former with the required restrictions on the name and the function-static-variables as specified. What has not been implemented is any clauses for this, any of the A.3.4 warnings, or the other form.
1 parent 4703f8b commit df1e102

37 files changed

+1191
-187
lines changed

clang/include/clang/AST/DeclOpenACC.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,61 @@ class OpenACCDeclareDecl final
101101
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
102102
static bool classofKind(Kind K) { return K == OpenACCDeclare; }
103103
};
104+
105+
class OpenACCRoutineDecl final
106+
: public OpenACCConstructDecl,
107+
private llvm::TrailingObjects<OpenACCRoutineDecl, const OpenACCClause *> {
108+
friend TrailingObjects;
109+
friend class ASTDeclReader;
110+
friend class ASTDeclWriter;
111+
112+
Expr *FuncRef = nullptr;
113+
SourceRange ParensLoc;
114+
115+
OpenACCRoutineDecl(unsigned NumClauses)
116+
: OpenACCConstructDecl(OpenACCRoutine) {
117+
std::uninitialized_value_construct(
118+
getTrailingObjects<const OpenACCClause *>(),
119+
getTrailingObjects<const OpenACCClause *>() + NumClauses);
120+
setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
121+
NumClauses));
122+
}
123+
124+
OpenACCRoutineDecl(DeclContext *DC, SourceLocation StartLoc,
125+
SourceLocation DirLoc, SourceLocation LParenLoc,
126+
Expr *FuncRef, SourceLocation RParenLoc,
127+
SourceLocation EndLoc,
128+
ArrayRef<const OpenACCClause *> Clauses)
129+
: OpenACCConstructDecl(OpenACCRoutine, DC, OpenACCDirectiveKind::Routine,
130+
StartLoc, DirLoc, EndLoc),
131+
FuncRef(FuncRef), ParensLoc(LParenLoc, RParenLoc) {
132+
// Initialize the trailing storage.
133+
std::uninitialized_copy(Clauses.begin(), Clauses.end(),
134+
getTrailingObjects<const OpenACCClause *>());
135+
setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
136+
Clauses.size()));
137+
}
138+
139+
public:
140+
static OpenACCRoutineDecl *
141+
Create(ASTContext &Ctx, DeclContext *DC, SourceLocation StartLoc,
142+
SourceLocation DirLoc, SourceLocation LParenLoc, Expr *FuncRef,
143+
SourceLocation RParenLoc, SourceLocation EndLoc,
144+
ArrayRef<const OpenACCClause *> Clauses);
145+
static OpenACCRoutineDecl *
146+
CreateDeserialized(ASTContext &Ctx, GlobalDeclID ID, unsigned NumClauses);
147+
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
148+
static bool classofKind(Kind K) { return K == OpenACCRoutine; }
149+
150+
const Expr *getFunctionReference() const { return FuncRef; }
151+
152+
Expr *getFunctionReference() { return FuncRef; }
153+
154+
SourceLocation getLParenLoc() const { return ParensLoc.getBegin(); }
155+
SourceLocation getRParenLoc() const { return ParensLoc.getEnd(); }
156+
157+
bool hasNameSpecified() const { return !ParensLoc.getBegin().isInvalid(); }
158+
};
104159
} // namespace clang
105160

106161
#endif

clang/include/clang/AST/JSONNodeDumper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ class JSONNodeDumper
282282
void VisitBlockDecl(const BlockDecl *D);
283283

284284
void VisitOpenACCDeclareDecl(const OpenACCDeclareDecl *D);
285+
void VisitOpenACCRoutineDecl(const OpenACCRoutineDecl *D);
285286

286287
void VisitDeclRefExpr(const DeclRefExpr *DRE);
287288
void VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E);

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1825,6 +1825,11 @@ DEF_TRAVERSE_DECL(OMPAllocateDecl, {
18251825
DEF_TRAVERSE_DECL(OpenACCDeclareDecl,
18261826
{ TRY_TO(VisitOpenACCClauseList(D->clauses())); })
18271827

1828+
DEF_TRAVERSE_DECL(OpenACCRoutineDecl, {
1829+
TRY_TO(TraverseStmt(D->getFunctionReference()));
1830+
TRY_TO(VisitOpenACCClauseList(D->clauses()));
1831+
})
1832+
18281833
// A helper method for TemplateDecl's children.
18291834
template <typename Derived>
18301835
bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(

clang/include/clang/AST/TextNodeDumper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ class TextNodeDumper
425425
void VisitOpenACCCacheConstruct(const OpenACCCacheConstruct *S);
426426
void VisitOpenACCAsteriskSizeExpr(const OpenACCAsteriskSizeExpr *S);
427427
void VisitOpenACCDeclareDecl(const OpenACCDeclareDecl *D);
428+
void VisitOpenACCRoutineDecl(const OpenACCRoutineDecl *D);
428429
void VisitEmbedExpr(const EmbedExpr *S);
429430
void VisitAtomicExpr(const AtomicExpr *AE);
430431
void VisitConvertVectorExpr(const ConvertVectorExpr *S);

clang/include/clang/Basic/Attr.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5026,3 +5026,11 @@ def Atomic : StmtAttr {
50265026
let Documentation = [AtomicDocs];
50275027
let StrictEnumParameters = 1;
50285028
}
5029+
5030+
def OpenACCRoutineAnnot : InheritableAttr {
5031+
// This attribute is used to mark that a function is targetted by a `routine`
5032+
// directive, so it dones't have a spelling and is always implicit.
5033+
let Spellings = [];
5034+
let Subjects = SubjectList<[Function]>;
5035+
let Documentation = [InternalOnly];
5036+
}

clang/include/clang/Basic/DeclNodes.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,4 @@ def RequiresExprBody : DeclNode<Decl>, DeclContext;
112112
def LifetimeExtendedTemporary : DeclNode<Decl>;
113113
def HLSLBuffer : DeclNode<Named, "HLSLBuffer">, DeclContext;
114114
def OpenACCDeclare : DeclNode<Decl, "#pragma acc declare">;
115+
def OpenACCRoutine : DeclNode<Decl, "#pragma acc routine">;

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12821,8 +12821,9 @@ def err_wasm_builtin_arg_must_be_integer_type : Error <
1282112821
"%ordinal0 argument must be an integer">;
1282212822

1282312823
// OpenACC diagnostics.
12824-
def warn_acc_construct_unimplemented
12825-
: Warning<"OpenACC construct '%0' not yet implemented, pragma ignored">,
12824+
def warn_acc_routine_unimplemented
12825+
: Warning<"OpenACC construct 'routine' with implicit function not yet "
12826+
"implemented, pragma ignored">,
1282612827
InGroup<SourceUsesOpenACC>;
1282712828
def warn_acc_clause_unimplemented
1282812829
: Warning<"OpenACC clause '%0' not yet implemented, clause ignored">,
@@ -13060,6 +13061,13 @@ def err_acc_declare_same_scope
1306013061
def err_acc_multiple_references
1306113062
: Error<"variable referenced in '%0' clause of OpenACC 'declare' directive "
1306213063
"was already referenced">;
13064+
def err_acc_routine_not_func
13065+
: Error<"OpenACC routine name '%0' does not name a function">;
13066+
def err_acc_routine_overload_set
13067+
: Error<"OpenACC routine name '%0' names a set of overloads">;
13068+
def err_acc_magic_static_in_routine
13069+
: Error<"function static variables are not permitted in functions to which "
13070+
"an OpenACC 'routine' directive applies">;
1306313071

1306413072
// AMDGCN builtins diagnostics
1306513073
def err_amdgcn_global_load_lds_size_invalid_value : Error<"invalid size value">;

clang/include/clang/Sema/Sema.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13436,6 +13436,10 @@ class Sema final : public SemaBase {
1343613436
bool ForCallExpr = false);
1343713437
ExprResult SubstExpr(Expr *E,
1343813438
const MultiLevelTemplateArgumentList &TemplateArgs);
13439+
/// Substitute an expression as if it is a address-of-operand, which makes it
13440+
/// act like a CXXIdExpression rather than an attempt to call.
13441+
ExprResult SubstCXXIdExpr(Expr *E,
13442+
const MultiLevelTemplateArgumentList &TemplateArgs);
1343913443

1344013444
// A RAII type used by the TemplateDeclInstantiator and TemplateInstantiator
1344113445
// to disable constraint evaluation, then restore the state.

clang/include/clang/Sema/SemaOpenACC.h

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@ class SemaOpenACC : public SemaBase {
167167
// contexts, we can just store the declaration and location of the reference.
168168
llvm::DenseMap<const clang::DeclaratorDecl *, SourceLocation>
169169
DeclareVarReferences;
170+
// The 'routine' construct disallows magic-statics in a function referred to
171+
// by a 'routine' directive. So record any of these that we see so we can
172+
// check them later.
173+
llvm::SmallDenseMap<const clang::FunctionDecl *, SourceLocation>
174+
MagicStaticLocs;
170175

171176
public:
172177
ComputeConstructInfo &getActiveComputeConstructInfo() {
@@ -723,6 +728,7 @@ class SemaOpenACC : public SemaBase {
723728
/// MiscLoc: First misc location, if necessary (not all constructs).
724729
/// Exprs: List of expressions on the construct itself, if necessary (not all
725730
/// constructs).
731+
/// FuncRef: used only for Routine, this is the function being referenced.
726732
/// AK: The atomic kind of the directive, if necessary (atomic only)
727733
/// RParenLoc: Location of the right paren, if it exists (not on all
728734
/// constructs).
@@ -735,23 +741,12 @@ class SemaOpenACC : public SemaBase {
735741
OpenACCAtomicKind AK, SourceLocation RParenLoc, SourceLocation EndLoc,
736742
ArrayRef<OpenACCClause *> Clauses, StmtResult AssocStmt);
737743

738-
StmtResult ActOnEndStmtDirective(
739-
OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc,
740-
SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs,
741-
SourceLocation RParenLoc, SourceLocation EndLoc,
742-
ArrayRef<OpenACCClause *> Clauses, StmtResult AssocStmt) {
743-
return ActOnEndStmtDirective(K, StartLoc, DirLoc, LParenLoc, MiscLoc, Exprs,
744-
OpenACCAtomicKind::None, RParenLoc, EndLoc,
745-
Clauses, AssocStmt);
746-
}
747-
748744
/// Called after the directive has been completely parsed, including the
749745
/// declaration group or associated statement.
750-
DeclGroupRef ActOnEndDeclDirective(OpenACCDirectiveKind K,
751-
SourceLocation StartLoc,
752-
SourceLocation DirLoc,
753-
SourceLocation EndLoc,
754-
ArrayRef<OpenACCClause *> Clauses);
746+
DeclGroupRef ActOnEndDeclDirective(
747+
OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc,
748+
SourceLocation LParenLoc, Expr *FuncRef, SourceLocation RParenLoc,
749+
SourceLocation EndLoc, ArrayRef<OpenACCClause *> Clauses);
755750

756751
/// Called when encountering an 'int-expr' for OpenACC, and manages
757752
/// conversions and diagnostics to 'int'.
@@ -764,6 +759,9 @@ class SemaOpenACC : public SemaBase {
764759
Expr *VarExpr);
765760
/// Helper function called by ActonVar that is used to check a 'cache' var.
766761
ExprResult ActOnCacheVar(Expr *VarExpr);
762+
/// Function called when a variable declarator is created, which lets us
763+
/// impelment the 'routine' 'function static variables' restriction.
764+
void ActOnVariableDeclarator(VarDecl *VD);
767765

768766
// Called after 'ActOnVar' specifically for a 'link' clause, which has to do
769767
// some minor additional checks.
@@ -773,6 +771,8 @@ class SemaOpenACC : public SemaBase {
773771
// checked during both phases of template translation.
774772
bool CheckDeclareClause(SemaOpenACC::OpenACCParsedClause &Clause);
775773

774+
ExprResult ActOnRoutineName(Expr *RoutineName);
775+
776776
/// Called while semantically analyzing the reduction clause, ensuring the var
777777
/// is the correct kind of reference.
778778
ExprResult CheckReductionVar(OpenACCDirectiveKind DirectiveKind,

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1531,7 +1531,10 @@ enum DeclCode {
15311531
// An OpenACCDeclareDecl record.
15321532
DECL_OPENACC_DECLARE,
15331533

1534-
DECL_LAST = DECL_OPENACC_DECLARE
1534+
// An OpenACCRoutineDecl record.
1535+
DECL_OPENACC_ROUTINE,
1536+
1537+
DECL_LAST = DECL_OPENACC_ROUTINE
15351538
};
15361539

15371540
/// Record codes for each kind of statement or expression.

clang/lib/AST/DeclBase.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
994994
case RequiresExprBody:
995995
case ImplicitConceptSpecialization:
996996
case OpenACCDeclare:
997+
case OpenACCRoutine:
997998
// Never looked up by name.
998999
return 0;
9991000
}

clang/lib/AST/DeclOpenACC.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,22 @@ OpenACCDeclareDecl::CreateDeserialized(ASTContext &Ctx, GlobalDeclID ID,
3131
return new (Ctx, ID, additionalSizeToAlloc<const OpenACCClause *>(NumClauses))
3232
OpenACCDeclareDecl(NumClauses);
3333
}
34+
35+
OpenACCRoutineDecl *
36+
OpenACCRoutineDecl::Create(ASTContext &Ctx, DeclContext *DC,
37+
SourceLocation StartLoc, SourceLocation DirLoc,
38+
SourceLocation LParenLoc, Expr *FuncRef,
39+
SourceLocation RParenLoc, SourceLocation EndLoc,
40+
ArrayRef<const OpenACCClause *> Clauses) {
41+
return new (Ctx, DC,
42+
additionalSizeToAlloc<const OpenACCClause *>(Clauses.size()))
43+
OpenACCRoutineDecl(DC, StartLoc, DirLoc, LParenLoc, FuncRef, RParenLoc,
44+
EndLoc, Clauses);
45+
}
46+
47+
OpenACCRoutineDecl *
48+
OpenACCRoutineDecl::CreateDeserialized(ASTContext &Ctx, GlobalDeclID ID,
49+
unsigned NumClauses) {
50+
return new (Ctx, ID, additionalSizeToAlloc<const OpenACCClause *>(NumClauses))
51+
OpenACCRoutineDecl(NumClauses);
52+
}

clang/lib/AST/DeclPrinter.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ namespace {
113113
void VisitHLSLBufferDecl(HLSLBufferDecl *D);
114114

115115
void VisitOpenACCDeclareDecl(OpenACCDeclareDecl *D);
116+
void VisitOpenACCRoutineDecl(OpenACCRoutineDecl *D);
116117

117118
void printTemplateParameters(const TemplateParameterList *Params,
118119
bool OmitTemplateKW = false);
@@ -497,7 +498,7 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
497498
isa<OMPDeclareMapperDecl>(*D) || isa<OMPRequiresDecl>(*D) ||
498499
isa<OMPAllocateDecl>(*D))
499500
Terminator = nullptr;
500-
else if (isa<OpenACCDeclareDecl>(*D))
501+
else if (isa<OpenACCDeclareDecl, OpenACCRoutineDecl>(*D))
501502
Terminator = nullptr;
502503
else if (isa<ObjCMethodDecl>(*D) && cast<ObjCMethodDecl>(*D)->hasBody())
503504
Terminator = nullptr;
@@ -1922,3 +1923,25 @@ void DeclPrinter::VisitOpenACCDeclareDecl(OpenACCDeclareDecl *D) {
19221923
Printer.VisitClauseList(D->clauses());
19231924
}
19241925
}
1926+
void DeclPrinter::VisitOpenACCRoutineDecl(OpenACCRoutineDecl *D) {
1927+
if (!D->isInvalidDecl()) {
1928+
Out << "#pragma acc routine";
1929+
1930+
if (D->hasNameSpecified()) {
1931+
Out << "(";
1932+
1933+
// The referenced function was named here, but this makes us tolerant of
1934+
// errors.
1935+
if (D->getFunctionReference())
1936+
D->getFunctionReference()->printPretty(Out, nullptr, Policy,
1937+
Indentation, "\n", &Context);
1938+
else
1939+
Out << "<error>";
1940+
1941+
Out << ")";
1942+
}
1943+
1944+
OpenACCClausePrinter Printer(Out, Policy);
1945+
Printer.VisitClauseList(D->clauses());
1946+
}
1947+
}

clang/lib/AST/JSONNodeDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,6 +1363,7 @@ void JSONNodeDumper::VisitOpenACCAsteriskSizeExpr(
13631363
const OpenACCAsteriskSizeExpr *E) {}
13641364

13651365
void JSONNodeDumper::VisitOpenACCDeclareDecl(const OpenACCDeclareDecl *D) {}
1366+
void JSONNodeDumper::VisitOpenACCRoutineDecl(const OpenACCRoutineDecl *D) {}
13661367

13671368
void JSONNodeDumper::VisitPredefinedExpr(const PredefinedExpr *PE) {
13681369
JOS.attribute("name", PredefinedExpr::getIdentKindName(PE->getIdentKind()));

clang/lib/AST/StmtPrinter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,8 @@ void StmtPrinter::VisitDeclStmt(DeclStmt *Node) {
264264
Indent();
265265
PrintRawDeclStmt(Node);
266266
// Certain pragma declarations shouldn't have a semi-colon after them.
267-
if (!Node->isSingleDecl() || !isa<OpenACCDeclareDecl>(Node->getSingleDecl()))
267+
if (!Node->isSingleDecl() ||
268+
!isa<OpenACCDeclareDecl, OpenACCRoutineDecl>(Node->getSingleDecl()))
268269
OS << ";";
269270
OS << NL;
270271
}

clang/lib/AST/TextNodeDumper.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3079,6 +3079,23 @@ void TextNodeDumper::VisitOpenACCDeclareDecl(const OpenACCDeclareDecl *D) {
30793079
AddChild([=] { Visit(S); });
30803080
});
30813081
}
3082+
void TextNodeDumper::VisitOpenACCRoutineDecl(const OpenACCRoutineDecl *D) {
3083+
OS << " " << D->getDirectiveKind();
3084+
3085+
if (D->hasNameSpecified()) {
3086+
OS << " name_specified";
3087+
dumpSourceRange(SourceRange{D->getLParenLoc(), D->getRParenLoc()});
3088+
}
3089+
3090+
AddChild([=] { Visit(D->getFunctionReference()); });
3091+
3092+
for (const OpenACCClause *C : D->clauses())
3093+
AddChild([=] {
3094+
Visit(C);
3095+
for (const Stmt *S : C->children())
3096+
AddChild([=] { Visit(S); });
3097+
});
3098+
}
30823099

30833100
void TextNodeDumper::VisitEmbedExpr(const EmbedExpr *S) {
30843101
AddChild("begin", [=] { OS << S->getStartingElementPos(); });

clang/lib/CodeGen/CGDecl.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
180180

181181
case Decl::OpenACCDeclare:
182182
return CGM.EmitOpenACCDeclare(cast<OpenACCDeclareDecl>(&D), this);
183+
case Decl::OpenACCRoutine:
184+
return CGM.EmitOpenACCRoutine(cast<OpenACCRoutineDecl>(&D), this);
183185

184186
case Decl::Typedef: // typedef int X;
185187
case Decl::TypeAlias: { // using X = int; [C++0x]
@@ -2852,6 +2854,11 @@ void CodeGenModule::EmitOpenACCDeclare(const OpenACCDeclareDecl *D,
28522854
// This is a no-op, we cna just ignore these declarations.
28532855
}
28542856

2857+
void CodeGenModule::EmitOpenACCRoutine(const OpenACCRoutineDecl *D,
2858+
CodeGenFunction *CGF) {
2859+
// This is a no-op, we cna just ignore these declarations.
2860+
}
2861+
28552862
void CodeGenModule::EmitOMPRequiresDecl(const OMPRequiresDecl *D) {
28562863
getOpenMPRuntime().processRequiresDirective(D);
28572864
}

clang/lib/CodeGen/CodeGenModule.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,6 +1575,8 @@ class CodeGenModule : public CodeGenTypeCache {
15751575

15761576
// Emit code for the OpenACC Declare declaration.
15771577
void EmitOpenACCDeclare(const OpenACCDeclareDecl *D, CodeGenFunction *CGF);
1578+
// Emit code for the OpenACC Routine declaration.
1579+
void EmitOpenACCRoutine(const OpenACCRoutineDecl *D, CodeGenFunction *CGF);
15781580

15791581
/// Emit a code for requires directive.
15801582
/// \param D Requires declaration

0 commit comments

Comments
 (0)