summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-06-06 17:25:21 +0000
committerJordan Rose <jordan_rose@apple.com>2012-06-06 17:25:21 +0000
commitccf43ca05cb1540f3d95a73b7b329bf926808c7b (patch)
treef1c81126e272ce660655dd437fa5dbf9d058f303 /clang/lib
parentfaa389462835ab40ed8af86eb32c44abfcf4e48a (diff)
downloadbcm5719-llvm-ccf43ca05cb1540f3d95a73b7b329bf926808c7b.tar.gz
bcm5719-llvm-ccf43ca05cb1540f3d95a73b7b329bf926808c7b.zip
Add pedantic warning -Wempty-translation-unit (C11 6.9p1).
In standard C since C89, a 'translation-unit' is syntactically defined to have at least one "external-declaration", which is either a decl or a function definition. In Clang the latter gives us a declaration as well. The tricky bit about this warning is that our predefines can contain external declarations (__builtin_va_list and the 128-bit integer types). Therefore our AST parser now makes sure we have at least one declaration that doesn't come from the predefines buffer. Also, remove bogus warning about empty source files. This doesn't catch source files that only contain comments, and never fired anyway because of our predefines. PR12665 and <rdar://problem/9165548> llvm-svn: 158085
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Basic/SourceManager.cpp1
-rw-r--r--clang/lib/Lex/Preprocessor.cpp2
-rw-r--r--clang/lib/Parse/ParseAST.cpp54
-rw-r--r--clang/lib/Parse/Parser.cpp4
4 files changed, 41 insertions, 20 deletions
diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp
index ed920eb4880..783e073e665 100644
--- a/clang/lib/Basic/SourceManager.cpp
+++ b/clang/lib/Basic/SourceManager.cpp
@@ -407,6 +407,7 @@ SourceManager::~SourceManager() {
void SourceManager::clearIDTables() {
MainFileID = FileID();
+ PredefinesFileID = FileID();
LocalSLocEntryTable.clear();
LoadedSLocEntryTable.clear();
SLocEntryLoaded.clear();
diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp
index d387f4392de..955c39cfe78 100644
--- a/clang/lib/Lex/Preprocessor.cpp
+++ b/clang/lib/Lex/Preprocessor.cpp
@@ -425,7 +425,7 @@ void Preprocessor::EnterMainSourceFile() {
llvm::MemoryBuffer *SB =
llvm::MemoryBuffer::getMemBufferCopy(Predefines, "<built-in>");
assert(SB && "Cannot create predefined source buffer");
- FileID FID = SourceMgr.createFileIDForMemBuffer(SB);
+ FileID FID = SourceMgr.createPredefinesFileIDForMemBuffer(SB);
assert(!FID.isInvalid() && "Could not create FileID for predefines?");
// Start parsing the predefines.
diff --git a/clang/lib/Parse/ParseAST.cpp b/clang/lib/Parse/ParseAST.cpp
index d1c2624f8cb..3f86c4d2c89 100644
--- a/clang/lib/Parse/ParseAST.cpp
+++ b/clang/lib/Parse/ParseAST.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Parse/ParseAST.h"
+#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/SemaConsumer.h"
@@ -77,27 +78,50 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
S.getPreprocessor().EnterMainSourceFile();
P.Initialize();
S.Initialize();
-
- if (ExternalASTSource *External = S.getASTContext().getExternalSource())
+
+ // C11 6.9p1 says translation units must have at least one top-level
+ // declaration. C++ doesn't have this restriction. We also don't want to
+ // complain if we have a precompiled header, although technically if the PCH
+ // is empty we should still emit the (pedantic) diagnostic.
+ bool WarnForEmptyTU = !S.getLangOpts().CPlusPlus;
+ if (ExternalASTSource *External = S.getASTContext().getExternalSource()) {
External->StartTranslationUnit(Consumer);
-
- bool Abort = false;
+ WarnForEmptyTU = false;
+ }
+
+ // Clang's predefines contain top-level declarations for things like va_list,
+ // making it hard to tell if the /user's/ translation unit has at least one
+ // top-level declaration. So we parse cautiously, looking for a declaration
+ // that doesn't come from our predefines.
+ // Note that ParseTopLevelDecl returns 'true' at EOF.
+ SourceManager &SM = S.getSourceManager();
Parser::DeclGroupPtrTy ADecl;
-
- while (!P.ParseTopLevelDecl(ADecl)) { // Not end of file.
- // If we got a null return and something *was* parsed, ignore it. This
- // is due to a top-level semicolon, an action override, or a parse error
- // skipping something.
+ while (WarnForEmptyTU && !P.ParseTopLevelDecl(ADecl)) {
if (ADecl) {
- if (!Consumer->HandleTopLevelDecl(ADecl.get())) {
- Abort = true;
- break;
+ if (!Consumer->HandleTopLevelDecl(ADecl.get()))
+ return;
+ if (DeclGroupRef::iterator FirstDecl = ADecl.get().begin()) {
+ SourceLocation DeclLoc = (*FirstDecl)->getLocation();
+ WarnForEmptyTU = SM.isFromPredefines(DeclLoc);
}
}
- };
+ }
- if (Abort)
- return;
+ // If we ended up seeing EOF before any top-level declarations, emit our
+ // diagnostic. Otherwise, parse the rest of the file normally.
+ if (WarnForEmptyTU) {
+ P.Diag(diag::ext_empty_translation_unit);
+ } else {
+ while (!P.ParseTopLevelDecl(ADecl)) { // Not end of file.
+ // If we got a null return and something *was* parsed, ignore it. This
+ // is due to a top-level semicolon, an action override, or a parse error
+ // skipping something.
+ if (ADecl) {
+ if (!Consumer->HandleTopLevelDecl(ADecl.get()))
+ return;
+ }
+ };
+ }
// Process any TopLevelDecls generated by #pragma weak.
for (SmallVector<Decl*,2>::iterator
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 504071405b7..f0e2b3aa85f 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -439,10 +439,6 @@ void Parser::Initialize() {
// Prime the lexer look-ahead.
ConsumeToken();
- if (Tok.is(tok::eof) &&
- !getLangOpts().CPlusPlus) // Empty source file is an extension in C
- Diag(Tok, diag::ext_empty_source_file);
-
// Initialization for Objective-C context sensitive keywords recognition.
// Referenced in Parser::ParseObjCTypeQualifierList.
if (getLangOpts().ObjC1) {
OpenPOWER on IntegriCloud