[OPENMP]Fix skipping of functions body.

When parsing the code with OpenMP and the function's body must be
skipped, need to skip also OpenMP annotation tokens. Otherwise the
counters for braces/parens are unbalanced and parsing fails.
This commit is contained in:
Alexey Bataev 2019-12-13 16:05:30 -05:00
parent e8af4fd42d
commit 8035bb4a65
6 changed files with 59 additions and 10 deletions

View File

@ -56,6 +56,7 @@ namespace clang {
///
class Parser : public CodeCompletionHandler {
friend class ColonProtectionRAIIObject;
friend class ParsingOpenMPDirectiveRAII;
friend class InMessageExpressionRAIIObject;
friend class PoisonSEHIdentifiersRAIIObject;
friend class ObjCDeclContextSwitch;
@ -215,6 +216,9 @@ class Parser : public CodeCompletionHandler {
/// ColonProtectionRAIIObject RAII object.
bool ColonIsSacred;
/// Parsing OpenMP directive mode.
bool OpenMPDirectiveParsing = false;
/// When true, we are directly inside an Objective-C message
/// send expression.
///

View File

@ -287,6 +287,25 @@ namespace clang {
}
};
/// Activates OpenMP parsing mode to preseve OpenMP specific annotation
/// tokens.
class ParsingOpenMPDirectiveRAII {
Parser &P;
bool OldVal;
public:
ParsingOpenMPDirectiveRAII(Parser &P)
: P(P), OldVal(P.OpenMPDirectiveParsing) {
P.OpenMPDirectiveParsing = true;
}
/// This can be used to restore the state early, before the dtor
/// is run.
void restore() { P.OpenMPDirectiveParsing = OldVal; }
~ParsingOpenMPDirectiveRAII() { restore(); }
};
/// RAII object that makes '>' behave either as an operator
/// or as the closing angle bracket for a template argument list.
class GreaterThanIsOperatorScope {

View File

@ -1332,6 +1332,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
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();
@ -1667,6 +1668,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
StmtResult
Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
ParsingOpenMPDirectiveRAII DirScope(*this);
ParenBraceBracketBalancer BalancerRAIIObj(*this);
SmallVector<OMPClause *, 5> Clauses;
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>

View File

@ -278,6 +278,10 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) {
case tok::annot_pragma_openmp:
case tok::annot_pragma_openmp_end:
// Stop before an OpenMP pragma boundary.
if (OpenMPDirectiveParsing)
return false;
ConsumeAnnotationToken();
break;
case tok::annot_module_begin:
case tok::annot_module_end:
case tok::annot_module_include:

View File

@ -0,0 +1,30 @@
// RUN: not %clang_cc1 -fsyntax-only -std=c++14 -code-completion-at=%s:28:5 -fopenmp %s -o - 2>&1 | FileCheck %s
template <class T>
auto make_func() {
struct impl {
impl* func() {
int x;
if (x = 10) {
#pragma omp parallel
;
}
// Check that body of this function is actually skipped.
// CHECK-NOT: crash-skipped-bodies-template-inst.cpp:7:{{[0-9]+}}: warning: using the result of an assignment as a condition without parentheses
return this;
}
};
int x;
if (x = 10) {}
// Check that this function is not skipped.
// CHECK: crash-skipped-bodies-template-inst.cpp:18:9: warning: using the result of an assignment as a condition without parentheses
return impl();
}
void foo() {
[]() {
make_func<int>();
m
// CHECK: COMPLETION: make_func : [#auto#]make_func<<#class T#>>()
};
}

View File

@ -19,7 +19,6 @@ int nested(int a) {
#if __cplusplus <= 199711L
// expected-warning@-2 {{'auto' type specifier is a C++11 extension}}
// expected-error@-3 {{expected expression}}
// expected-error@-4 {{expected ';' at end of declaration}}
#endif
#pragma omp parallel
@ -29,14 +28,5 @@ int nested(int a) {
}
};
F();
#if __cplusplus <= 199711L
// expected-error@-2 {{C++ requires a type specifier for all declarations}}
#endif
return a;
#if __cplusplus <= 199711L
// expected-error@-2 {{expected unqualified-id}}
#endif
}
#if __cplusplus <= 199711L
// expected-error@-2 {{extraneous closing brace ('}')}}
#endif