Skip to content

Commit

Permalink
[Parser] Emit descriptive diagnostic for misplaced pragma
Browse files Browse the repository at this point in the history
If a class or struct or union declaration contains a pragma that
is not valid in this context, compiler issues generic error like
"expected member name or ';' after declaration specifiers". With this
change the error tells that this pragma cannot appear in this declaration.

Differential Revision: https://reviews.llvm.org/D64932

llvm-svn: 367779
  • Loading branch information
spavloff committed Aug 4, 2019
1 parent 8f6cf97 commit 037861b
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 2 deletions.
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Expand Up @@ -974,6 +974,8 @@ def warn_pragma_missing_argument : Warning<
def warn_pragma_invalid_argument : Warning<
"unexpected argument '%0' to '#pragma %1'%select{|; expected %3}2">, InGroup<IgnoredPragmas>;

def err_pragma_misplaced_in_decl : Error<"this pragma cannot appear in %0 declaration">;

// '#pragma clang section' related errors
def err_pragma_expected_clang_section_name : Error<
"expected one of [bss|data|rodata|text] section kind in '#pragma %0'">;
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/Parse/ParseDecl.cpp
Expand Up @@ -4148,6 +4148,14 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
continue;
}

if (tok::isPragmaAnnotation(Tok.getKind())) {
Diag(Tok.getLocation(), diag::err_pragma_misplaced_in_decl)
<< DeclSpec::getSpecifierName(
TagType, Actions.getASTContext().getPrintingPolicy());
ConsumeAnnotationToken();
continue;
}

if (!Tok.is(tok::at)) {
auto CFieldCallback = [&](ParsingFieldDeclarator &FD) {
// Install the declarator into the current TagDecl.
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/Parse/ParseDeclCXX.cpp
Expand Up @@ -3134,6 +3134,13 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas(
TagDecl);

default:
if (tok::isPragmaAnnotation(Tok.getKind())) {
Diag(Tok.getLocation(), diag::err_pragma_misplaced_in_decl)
<< DeclSpec::getSpecifierName(TagType,
Actions.getASTContext().getPrintingPolicy());
ConsumeAnnotationToken();
return nullptr;
}
return ParseCXXClassMemberDeclaration(AS, AccessAttrs);
}
}
Expand Down
3 changes: 1 addition & 2 deletions clang/test/Parser/pragma-attribute-context.cpp
Expand Up @@ -31,8 +31,7 @@ int c = my_ns::nested::h(); // expected-warning{{'h' is only available on macOS

struct InStruct {
// FIXME: This asserts in Objective-C++!
// FIXME: This is a horrible diagnostic!
#ifndef __OBJC__
BEGIN_PRAGMA // expected-error {{expected member name or ';' after declaration specifiers}}
BEGIN_PRAGMA // expected-error {{this pragma cannot appear in struct declaration}}
#endif
};
13 changes: 13 additions & 0 deletions clang/test/Parser/pragma-fp-contract.c
Expand Up @@ -10,3 +10,16 @@ void f2(void) {
#pragma STDC FP_CONTRACT OFF
#pragma STDC FP_CONTRACT ON
}

struct S1 {
// expected-error@+1 {{this pragma cannot appear in struct declaration}}
#pragma STDC FP_CONTRACT ON
float f1;
};

union U1 {
float f1;
float f2;
// expected-error@+1 {{this pragma cannot appear in union declaration}}
#pragma STDC FP_CONTRACT ON
};
32 changes: 32 additions & 0 deletions clang/test/Parser/pragma-fp-contract.cpp
@@ -0,0 +1,32 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s

void f1(void) {
int x = 0;
/* expected-error@+1 {{'#pragma fp_contract' can only appear at file scope or at the start of a compound statement}} */
#pragma STDC FP_CONTRACT ON
}

void f2(void) {
#pragma STDC FP_CONTRACT OFF
#pragma STDC FP_CONTRACT ON
}

struct S1 {
// expected-error@+1 {{this pragma cannot appear in struct declaration}}
#pragma STDC FP_CONTRACT ON
float f1;
};

union U1 {
float f1;
float f2;
// expected-error@+1 {{this pragma cannot appear in union declaration}}
#pragma STDC FP_CONTRACT ON
};

class C1 {
float f1;
// expected-error@+1 {{this pragma cannot appear in class declaration}}
#pragma STDC FP_CONTRACT ON
float f2;
};

0 comments on commit 037861b

Please sign in to comment.