[clang] c972f6f - [OPENMP]Allow using of members in standalone declaration pragmas.
Alexey Bataev via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 7 10:58:05 PST 2020
Author: Alexey Bataev
Date: 2020-01-07T13:44:10-05:00
New Revision: c972f6fd7919b737f4c991d27249b9a947011c8e
URL: https://github.com/llvm/llvm-project/commit/c972f6fd7919b737f4c991d27249b9a947011c8e
DIFF: https://github.com/llvm/llvm-project/commit/c972f6fd7919b737f4c991d27249b9a947011c8e.diff
LOG: [OPENMP]Allow using of members in standalone declaration pragmas.
If standalone OpenMP declaration pragma, like declare mapper or declare
reduction, is declared in the class context, it may reference a member
(data or function) in its internal expressions/statements. So, the
parsing of such pragmas must be dalayed just like the parsing of the
member initializers/definitions before the completion of the class
declaration.
Added:
Modified:
clang/include/clang/Parse/Parser.h
clang/lib/Parse/ParseCXXInlineMethods.cpp
clang/lib/Parse/ParseDeclCXX.cpp
clang/lib/Parse/ParseOpenMP.cpp
clang/test/OpenMP/declare_mapper_messages.cpp
clang/test/OpenMP/declare_reduction_codegen.cpp
clang/test/OpenMP/declare_reduction_messages.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 4778dc9d3df8..e7130d2fe68e 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1153,6 +1153,7 @@ class Parser : public CodeCompletionHandler {
virtual void ParseLexedMemberInitializers();
virtual void ParseLexedMethodDefs();
virtual void ParseLexedAttributes();
+ virtual void ParseLexedPragmas();
};
/// Inner node of the LateParsedDeclaration tree that parses
@@ -1166,6 +1167,7 @@ class Parser : public CodeCompletionHandler {
void ParseLexedMemberInitializers() override;
void ParseLexedMethodDefs() override;
void ParseLexedAttributes() override;
+ void ParseLexedPragmas() override;
private:
Parser *Self;
@@ -1195,6 +1197,26 @@ class Parser : public CodeCompletionHandler {
void addDecl(Decl *D) { Decls.push_back(D); }
};
+ /// Contains the lexed tokens of a pragma with arguments that
+ /// may reference member variables and so need to be parsed at the
+ /// end of the class declaration after parsing all other member
+ /// member declarations.
+ class LateParsedPragma : public LateParsedDeclaration {
+ Parser *Self = nullptr;
+ AccessSpecifier AS = AS_none;
+ CachedTokens Toks;
+
+ public:
+ explicit LateParsedPragma(Parser *P, AccessSpecifier AS)
+ : Self(P), AS(AS) {}
+
+ void takeToks(CachedTokens &Cached) { Toks.swap(Cached); }
+ const CachedTokens &toks() const { return Toks; }
+ AccessSpecifier getAccessSpecifier() const { return AS; }
+
+ void ParseLexedPragmas() override;
+ };
+
// A list of late-parsed attributes. Used by ParseGNUAttributes.
class LateParsedAttrList: public SmallVector<LateParsedAttribute *, 2> {
public:
@@ -1454,6 +1476,8 @@ class Parser : public CodeCompletionHandler {
void ParseLexedMemberInitializers(ParsingClass &Class);
void ParseLexedMemberInitializer(LateParsedMemberInitializer &MI);
void ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod);
+ void ParseLexedPragmas(ParsingClass &Class);
+ void ParseLexedPragma(LateParsedPragma &LP);
bool ConsumeAndStoreFunctionPrologue(CachedTokens &Toks);
bool ConsumeAndStoreInitializer(CachedTokens &Toks, CachedInitKind CIK);
bool ConsumeAndStoreConditional(CachedTokens &Toks);
@@ -2875,7 +2899,7 @@ class Parser : public CodeCompletionHandler {
/// Parses declarative OpenMP directives.
DeclGroupPtrTy ParseOpenMPDeclarativeDirectiveWithExtDecl(
AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
- DeclSpec::TST TagType = DeclSpec::TST_unspecified,
+ bool Delayed = false, DeclSpec::TST TagType = DeclSpec::TST_unspecified,
Decl *TagDecl = nullptr);
/// Parse 'omp declare reduction' construct.
DeclGroupPtrTy ParseOpenMPDeclareReductionDirective(AccessSpecifier AS);
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index aa314da8e5b4..f8b5fec43800 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -223,6 +223,7 @@ Parser::LateParsedDeclaration::~LateParsedDeclaration() {}
void Parser::LateParsedDeclaration::ParseLexedMethodDeclarations() {}
void Parser::LateParsedDeclaration::ParseLexedMemberInitializers() {}
void Parser::LateParsedDeclaration::ParseLexedMethodDefs() {}
+void Parser::LateParsedDeclaration::ParseLexedPragmas() {}
Parser::LateParsedClass::LateParsedClass(Parser *P, ParsingClass *C)
: Self(P), Class(C) {}
@@ -243,6 +244,10 @@ void Parser::LateParsedClass::ParseLexedMethodDefs() {
Self->ParseLexedMethodDefs(*Class);
}
+void Parser::LateParsedClass::ParseLexedPragmas() {
+ Self->ParseLexedPragmas(*Class);
+}
+
void Parser::LateParsedMethodDeclaration::ParseLexedMethodDeclarations() {
Self->ParseLexedMethodDeclaration(*this);
}
@@ -255,6 +260,10 @@ void Parser::LateParsedMemberInitializer::ParseLexedMemberInitializers() {
Self->ParseLexedMemberInitializer(*this);
}
+void Parser::LateParsedPragma::ParseLexedPragmas() {
+ Self->ParseLexedPragma(*this);
+}
+
/// ParseLexedMethodDeclarations - We finished parsing the member
/// specification of a top (non-nested) C++ class. Now go over the
/// stack of method declarations with some parts for which parsing was
@@ -651,6 +660,43 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) {
ConsumeAnyToken();
}
+void Parser::ParseLexedPragmas(ParsingClass &Class) {
+ bool HasTemplateScope = !Class.TopLevelClass && Class.TemplateScope;
+ ParseScope ClassTemplateScope(this, Scope::TemplateParamScope,
+ HasTemplateScope);
+ TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
+ if (HasTemplateScope) {
+ Actions.ActOnReenterTemplateScope(getCurScope(), Class.TagOrTemplate);
+ ++CurTemplateDepthTracker;
+ }
+ bool HasClassScope = !Class.TopLevelClass;
+ ParseScope ClassScope(this, Scope::ClassScope | Scope::DeclScope,
+ HasClassScope);
+
+ for (LateParsedDeclaration *LPD : Class.LateParsedDeclarations)
+ LPD->ParseLexedPragmas();
+}
+
+void Parser::ParseLexedPragma(LateParsedPragma &LP) {
+ PP.EnterToken(Tok, /*IsReinject=*/true);
+ PP.EnterTokenStream(LP.toks(), /*DisableMacroExpansion=*/true,
+ /*IsReinject=*/true);
+
+ // Consume the previously pushed token.
+ ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
+ assert(Tok.isAnnotation() && "Expected annotation token.");
+ switch (Tok.getKind()) {
+ case tok::annot_pragma_openmp: {
+ AccessSpecifier AS = LP.getAccessSpecifier();
+ ParsedAttributesWithRange Attrs(AttrFactory);
+ (void)ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs);
+ break;
+ }
+ default:
+ llvm_unreachable("Unexpected token.");
+ }
+}
+
/// ConsumeAndStoreUntil - Consume and store the token at the passed token
/// container until the token 'T' is reached (which gets
/// consumed/stored too, if ConsumeFinalToken).
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index fe409327bfb4..ca2497ef6121 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -3136,8 +3136,8 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas(
}
case tok::annot_pragma_openmp:
- return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, AccessAttrs, TagType,
- TagDecl);
+ return ParseOpenMPDeclarativeDirectiveWithExtDecl(
+ AS, AccessAttrs, /*Delayed=*/true, TagType, TagDecl);
default:
if (tok::isPragmaAnnotation(Tok.getKind())) {
@@ -3355,6 +3355,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
// declarations and the lexed inline method definitions, along with any
// delayed attributes.
SourceLocation SavedPrevTokLocation = PrevTokLocation;
+ ParseLexedPragmas(getCurrentClass());
ParseLexedAttributes(getCurrentClass());
ParseLexedMethodDeclarations(getCurrentClass());
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index aaef4cd36d3b..31ae3af70b71 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -1336,14 +1336,45 @@ void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
/// annot_pragma_openmp_end
///
Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
- AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
+ AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed,
DeclSpec::TST TagType, Decl *Tag) {
assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
ParsingOpenMPDirectiveRAII DirScope(*this);
ParenBraceBracketBalancer BalancerRAIIObj(*this);
- SourceLocation Loc = ConsumeAnnotationToken();
- OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
+ SourceLocation Loc;
+ OpenMPDirectiveKind DKind;
+ if (Delayed) {
+ TentativeParsingAction TPA(*this);
+ Loc = ConsumeAnnotationToken();
+ DKind = parseOpenMPDirectiveKind(*this);
+ if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
+ // Need to delay parsing until completion of the parent class.
+ TPA.Revert();
+ CachedTokens Toks;
+ unsigned Cnt = 1;
+ Toks.push_back(Tok);
+ while (Cnt && Tok.isNot(tok::eof)) {
+ (void)ConsumeAnyToken();
+ if (Tok.is(tok::annot_pragma_openmp))
+ ++Cnt;
+ else if (Tok.is(tok::annot_pragma_openmp_end))
+ --Cnt;
+ Toks.push_back(Tok);
+ }
+ // Skip last annot_pragma_openmp_end.
+ if (Cnt == 0)
+ (void)ConsumeAnyToken();
+ auto *LP = new LateParsedPragma(this, AS);
+ LP->takeToks(Toks);
+ getCurrentClass().LateParsedDeclarations.push_back(LP);
+ return nullptr;
+ }
+ TPA.Commit();
+ } else {
+ Loc = ConsumeAnnotationToken();
+ DKind = parseOpenMPDirectiveKind(*this);
+ }
switch (DKind) {
case OMPD_threadprivate: {
@@ -1495,7 +1526,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
DeclGroupPtrTy Ptr;
if (Tok.is(tok::annot_pragma_openmp)) {
- Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
+ Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
+ TagType, Tag);
} else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
// Here we expect to see some function declaration.
if (AS == AS_none) {
diff --git a/clang/test/OpenMP/declare_mapper_messages.cpp b/clang/test/OpenMP/declare_mapper_messages.cpp
index 7b50fb2a52c2..bd91cdad8f40 100644
--- a/clang/test/OpenMP/declare_mapper_messages.cpp
+++ b/clang/test/OpenMP/declare_mapper_messages.cpp
@@ -8,12 +8,12 @@
int temp; // expected-note {{'temp' declared here}}
-class vec { // expected-note {{definition of 'vec' is not complete until the closing '}'}}
+class vec {
private:
int p; // expected-note {{declared private here}}
public:
int len;
-#pragma omp declare mapper(id: vec v) map(v.len) // expected-error {{member access into incomplete type 'vec'}}
+#pragma omp declare mapper(id: vec v) map(v.len)
double *data;
};
diff --git a/clang/test/OpenMP/declare_reduction_codegen.cpp b/clang/test/OpenMP/declare_reduction_codegen.cpp
index 1f6fa2bebea3..129823c6bf6a 100644
--- a/clang/test/OpenMP/declare_reduction_codegen.cpp
+++ b/clang/test/OpenMP/declare_reduction_codegen.cpp
@@ -69,6 +69,8 @@ struct SSS {
T a;
SSS() : a() {}
#pragma omp declare reduction(fun : T : omp_out ^= omp_in) initializer(omp_priv = 24 + omp_orig)
+#pragma omp declare reduction(sssss : T : ssssss(omp_in)) initializer(omp_priv = 18 + omp_orig)
+ static void ssssss(T &x);
};
SSS<int> d;
@@ -85,6 +87,17 @@ SSS<int> d;
// CHECK-NEXT: ret void
// CHECK-NEXT: }
+// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias %0, i32* noalias %1)
+// CHECK: call void @_ZN3SSSIiE6ssssssERi(i32* dereferenceable{{.*}})
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
+// CHECK: define internal {{.*}}void @{{[^(]+}}(i32* noalias %0, i32* noalias %1)
+// CHECK: [[ADD:%.+]] = add nsw i32 18,
+// CHECK-NEXT: store i32 [[ADD]], i32*
+// CHECK-NEXT: ret void
+// CHECK-NEXT: }
+
template <typename T>
void init(T &lhs, T &rhs) {}
diff --git a/clang/test/OpenMP/declare_reduction_messages.cpp b/clang/test/OpenMP/declare_reduction_messages.cpp
index eeafe9032e08..b1e59591d998 100644
--- a/clang/test/OpenMP/declare_reduction_messages.cpp
+++ b/clang/test/OpenMP/declare_reduction_messages.cpp
@@ -166,6 +166,8 @@ struct S
void foo(S &x) {};
// expected-error at +1 {{too many arguments to function call, expected single argument 'x', have 2 arguments}}
#pragma omp declare reduction (foo : U, S : omp_out.foo(omp_in, false))
+ #pragma omp declare reduction (xxx : U, S : bar(omp_in)) // expected-error {{non-const lvalue reference to type 'S<1>' cannot bind to a value of unrelated type 'U'}}
+ static void bar(S &x); // expected-note {{passing argument to parameter 'x' here}}
};
// expected-warning at +2 {{extra tokens at the end of '#pragma omp declare reduction' are ignored}}
// expected-note at +1 {{in instantiation of template class 'S<1>' requested here}}
More information about the cfe-commits
mailing list