forked from OSchip/llvm-project
[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:
parent
e8af4fd42d
commit
8035bb4a65
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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#>>()
|
||||
};
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue