[AST] Fix -ast-print for _Bool when have diagnostics

For example, given:

  #define bool _Bool
  _Bool i;
  void fn() { 1; }

-ast-print produced:

  tmp.c:3:13: warning: expression result unused
  void fn() { 1; }
              ^
  bool i;
  void fn() {
      1;
  }

That fails to compile because bool is undefined.

Details:

Diagnostics print _Bool as bool when the latter is defined as the
former.  However, diagnostics were altering the printing policy for
-ast-print as well.  The printed source was then invalid because the
preprocessor eats the bool definition.

Problematic diagnostics included suppressed warnings (e.g., add
-Wno-unused-value to the above example), including those that are
suppressed by default.

This patch fixes this bug and cleans up some related comments.

Reviewed by: aaron.ballman, rsmith

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

llvm-svn: 332275
This commit is contained in:
Joel E. Denny 2018-05-14 18:41:44 +00:00
parent 215ce4a1ca
commit 7bcc21027d
4 changed files with 54 additions and 8 deletions

View File

@ -2113,12 +2113,12 @@ public:
void checkPartialSpecializationVisibility(SourceLocation Loc,
NamedDecl *Spec);
/// Retrieve a suitable printing policy.
/// Retrieve a suitable printing policy for diagnostics.
PrintingPolicy getPrintingPolicy() const {
return getPrintingPolicy(Context, PP);
}
/// Retrieve a suitable printing policy.
/// Retrieve a suitable printing policy for diagnostics.
static PrintingPolicy getPrintingPolicy(const ASTContext &Ctx,
const Preprocessor &PP);

View File

@ -87,9 +87,10 @@ namespace {
<< DC->getPrimaryContext() << "\n";
} else
Out << "Not a DeclContext\n";
} else if (OutputKind == Print)
D->print(Out, /*Indentation=*/0, /*PrintInstantiation=*/true);
else if (OutputKind != None)
} else if (OutputKind == Print) {
PrintingPolicy Policy(D->getASTContext().getLangOpts());
D->print(Out, Policy, /*Indentation=*/0, /*PrintInstantiation=*/true);
} else if (OutputKind != None)
D->dump(Out, OutputKind == DumpFull);
}

View File

@ -52,8 +52,8 @@ ModuleLoader &Sema::getModuleLoader() const { return PP.getModuleLoader(); }
PrintingPolicy Sema::getPrintingPolicy(const ASTContext &Context,
const Preprocessor &PP) {
PrintingPolicy Policy = Context.getPrintingPolicy();
// Our printing policy is copied over the ASTContext printing policy whenever
// a diagnostic is emitted, so recompute it.
// In diagnostics, we print _Bool as bool if the latter is defined as the
// former.
Policy.Bool = Context.getLangOpts().Bool;
if (!Policy.Bool) {
if (const MacroInfo *BoolMacro = PP.getMacroInfo(Context.getBoolName())) {
@ -1287,7 +1287,8 @@ void Sema::EmitCurrentDiagnostic(unsigned DiagID) {
}
}
// Set up the context's printing policy based on our current state.
// Copy the diagnostic printing policy over the ASTContext printing policy.
// TODO: Stop doing that. See: https://reviews.llvm.org/D45093#1090292
Context.setPrintingPolicy(getPrintingPolicy());
// Emit the diagnostic.

View File

@ -0,0 +1,44 @@
// RUN: %clang_cc1 -verify -ast-print %s -xc -DDEF_BOOL_CBOOL \
// RUN: | FileCheck %s --check-prefixes=BOOL-AS-CBOOL,CBOOL
//
// RUN: %clang_cc1 -verify -ast-print %s -xc -DDEF_BOOL_CBOOL -DDIAG \
// RUN: | FileCheck %s --check-prefixes=BOOL-AS-CBOOL,CBOOL
//
// RUN: %clang_cc1 -verify -ast-print %s -xc -DDEF_BOOL_INT \
// RUN: | FileCheck %s --check-prefixes=BOOL-AS-INT,CBOOL
//
// RUN: %clang_cc1 -verify -ast-print %s -xc -DDEF_BOOL_INT -DDIAG \
// RUN: | FileCheck %s --check-prefixes=BOOL-AS-INT,CBOOL
//
// RUN: %clang_cc1 -verify -ast-print %s -xc++ \
// RUN: | FileCheck %s --check-prefixes=BOOL-AS-BOOL
//
// RUN: %clang_cc1 -verify -ast-print %s -xc++ -DDIAG \
// RUN: | FileCheck %s --check-prefixes=BOOL-AS-BOOL
#if DEF_BOOL_CBOOL
# define bool _Bool
#elif DEF_BOOL_INT
# define bool int
#endif
// BOOL-AS-CBOOL: _Bool i;
// BOOL-AS-INT: int i;
// BOOL-AS-BOOL: bool i;
bool i;
#ifndef __cplusplus
// CBOOL: _Bool j;
_Bool j;
#endif
// Induce a diagnostic (and verify we actually managed to do so), which used to
// permanently alter the -ast-print printing policy for _Bool. How bool is
// defined by the preprocessor is examined only once per compilation, when the
// diagnostic is emitted, and it used to affect the entirety of -ast-print, so
// test only one definition of bool per compilation.
#if DIAG
void fn() { 1; } // expected-warning {{expression result unused}}
#else
// expected-no-diagnostics
#endif