зеркало из https://github.com/microsoft/clang-1.git
Several fixes/simplifications surrounding how we stream top-level decl AST's.
The following code... typedef struct cssm_data {} CSSM_DATA, *CSSM_DATA_PTR; struct Y { int A; }; struct X { int A; } D; struct X E, F; ...now produces the following output... > ../../Debug/bin/clang xx.c -ast-print Read top-level tag decl: 'cssm_data' typedef struct cssm_data CSSM_DATA; typedef struct cssm_data *CSSM_DATA_PTR; Read top-level tag decl: 'Y' Read top-level tag decl: 'X' Read top-level variable decl: 'D' Read top-level variable decl: 'E' Read top-level variable decl: 'F' ...which is much more accurate than the previous -ast-print output... typedef struct cssm_data CSSM_DATA; typedef struct cssm_data CSSM_DATA; Read top-level variable decl: 'D' Read top-level variable decl: 'E' Read top-level variable decl: 'E' git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44421 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
ea75c55990
Коммит
1f64432558
|
@ -331,6 +331,8 @@ namespace {
|
|||
PrintObjcCompatibleAliasDecl(OID);
|
||||
} else if (isa<ObjcClassDecl>(D)) {
|
||||
Out << "@class [printing todo]\n";
|
||||
} else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
|
||||
Out << "Read top-level tag decl: '" << TD->getName() << "'\n";
|
||||
} else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
|
||||
Out << "Read top-level variable decl: '" << SD->getName() << "'\n";
|
||||
} else {
|
||||
|
|
|
@ -259,11 +259,10 @@ void Parser::Initialize() {
|
|||
|
||||
/// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
|
||||
/// action tells us to. This returns true if the EOF was encountered.
|
||||
bool Parser::ParseTopLevelDecl(DeclTy*& Result) {
|
||||
Result = 0;
|
||||
bool Parser::ParseTopLevelDecl() {
|
||||
if (Tok.is(tok::eof)) return true;
|
||||
|
||||
Result = ParseExternalDeclaration();
|
||||
ParseExternalDeclaration();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -281,8 +280,7 @@ void Parser::Finalize() {
|
|||
void Parser::ParseTranslationUnit() {
|
||||
Initialize();
|
||||
|
||||
DeclTy *Res;
|
||||
while (!ParseTopLevelDecl(Res))
|
||||
while (!ParseTopLevelDecl())
|
||||
/*parse them all*/;
|
||||
|
||||
Finalize();
|
||||
|
|
|
@ -24,10 +24,10 @@ ASTConsumer::~ASTConsumer() {}
|
|||
namespace {
|
||||
class ASTStreamer {
|
||||
Parser P;
|
||||
std::vector<Decl*> LastInGroupList;
|
||||
std::vector<Decl*> TopLevelDeclList;
|
||||
public:
|
||||
ASTStreamer(Preprocessor &pp, ASTContext &ctxt, unsigned MainFileID)
|
||||
: P(pp, *new Sema(pp, ctxt, LastInGroupList)) {
|
||||
: P(pp, *new Sema(pp, ctxt, TopLevelDeclList)) {
|
||||
pp.EnterMainSourceFile(MainFileID);
|
||||
|
||||
// Initialize the parser.
|
||||
|
@ -53,29 +53,28 @@ Decl *ASTStreamer::ReadTopLevelDecl() {
|
|||
|
||||
/// If the previous time through we read something like 'int X, Y', return
|
||||
/// the next declarator.
|
||||
if (!LastInGroupList.empty()) {
|
||||
Result = LastInGroupList.back();
|
||||
LastInGroupList.pop_back();
|
||||
if (!TopLevelDeclList.empty()) {
|
||||
Result = TopLevelDeclList.back();
|
||||
TopLevelDeclList.pop_back();
|
||||
return static_cast<Decl*>(Result);
|
||||
}
|
||||
|
||||
do {
|
||||
if (P.ParseTopLevelDecl(Result))
|
||||
if (P.ParseTopLevelDecl())
|
||||
return 0; // End of file.
|
||||
|
||||
// If we got a null return and something *was* parsed, try again. This
|
||||
// is due to a top-level semicolon, an action override, or a parse error
|
||||
// skipping something.
|
||||
} while (Result == 0);
|
||||
} while (TopLevelDeclList.size() == 0);
|
||||
|
||||
// If we parsed a declspec with multiple declarators, reverse the list and
|
||||
// return the first one.
|
||||
if (!LastInGroupList.empty()) {
|
||||
LastInGroupList.push_back((Decl*)Result);
|
||||
std::reverse(LastInGroupList.begin(), LastInGroupList.end());
|
||||
Result = LastInGroupList.back();
|
||||
LastInGroupList.pop_back();
|
||||
}
|
||||
if (TopLevelDeclList.size() > 1)
|
||||
std::reverse(TopLevelDeclList.begin(), TopLevelDeclList.end());
|
||||
|
||||
Result = TopLevelDeclList.back();
|
||||
TopLevelDeclList.pop_back();
|
||||
|
||||
return static_cast<Decl*>(Result);
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ QualType Sema::GetObjcProtoType(SourceLocation Loc) {
|
|||
}
|
||||
|
||||
Sema::Sema(Preprocessor &pp, ASTContext &ctxt, std::vector<Decl*> &prevInGroup)
|
||||
: PP(pp), Context(ctxt), CurFunctionDecl(0), LastInGroupList(prevInGroup) {
|
||||
: PP(pp), Context(ctxt), CurFunctionDecl(0), TopLevelDeclList(prevInGroup) {
|
||||
|
||||
// Get IdentifierInfo objects for known functions for which we
|
||||
// do extra checking.
|
||||
|
|
10
Sema/Sema.h
10
Sema/Sema.h
|
@ -69,11 +69,9 @@ class Sema : public Action {
|
|||
/// the method decl for the method being parsed.
|
||||
ObjcMethodDecl *CurMethodDecl;
|
||||
|
||||
/// LastInGroupList - This vector is populated when there are multiple
|
||||
/// declarators in a single decl group (e.g. "int A, B, C"). In this case,
|
||||
/// all but the last decl will be entered into this. This is used by the
|
||||
/// ASTStreamer.
|
||||
std::vector<Decl*> &LastInGroupList;
|
||||
/// TopLevelDeclList - This vector is populated with all declarators from
|
||||
/// a top-level declaration. This is used by the ASTStreamer.
|
||||
std::vector<Decl*> &TopLevelDeclList;
|
||||
|
||||
/// LabelMap - This is a mapping from label identifiers to the LabelStmt for
|
||||
/// it (which acts like the label decl in some ways). Forward referenced
|
||||
|
@ -231,7 +229,7 @@ private:
|
|||
VarDecl *MergeVarDecl(VarDecl *New, ScopedDecl *Old);
|
||||
/// AddTopLevelDecl - called after the decl has been fully processed.
|
||||
/// Allows for bookkeeping and post-processing of each declaration.
|
||||
void AddTopLevelDecl(Decl *current, Decl *last);
|
||||
void AddTopLevelDecl(Decl *current);
|
||||
|
||||
/// More parsing and symbol table subroutines...
|
||||
ParmVarDecl *ActOnParamDeclarator(struct DeclaratorChunk::ParamInfo &PI,
|
||||
|
|
|
@ -192,7 +192,7 @@ ScopedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid,
|
|||
II->setFETokenInfo(New);
|
||||
}
|
||||
// Make sure clients iterating over decls see this.
|
||||
LastInGroupList.push_back(New);
|
||||
AddTopLevelDecl(New);
|
||||
|
||||
return New;
|
||||
}
|
||||
|
@ -678,7 +678,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
|
|||
}
|
||||
|
||||
if (S->getParent() == 0)
|
||||
AddTopLevelDecl(New, LastDeclarator);
|
||||
AddTopLevelDecl(New);
|
||||
|
||||
// If any semantic error occurred, mark the decl as invalid.
|
||||
if (D.getInvalidType() || InvalidDecl)
|
||||
|
@ -973,7 +973,7 @@ void Sema::ObjcActOnStartOfMethodDef(Scope *FnBodyScope, DeclTy *D) {
|
|||
NewFD->setNext(II->getFETokenInfo<ScopedDecl>());
|
||||
II->setFETokenInfo(NewFD);
|
||||
GlobalScope->AddDecl(NewFD);
|
||||
AddTopLevelDecl(NewFD, 0);
|
||||
AddTopLevelDecl(NewFD);
|
||||
|
||||
// Allow all of Sema to see that we are entering a method definition.
|
||||
CurMethodDecl = MDecl;
|
||||
|
@ -1683,6 +1683,12 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,
|
|||
break;
|
||||
}
|
||||
|
||||
// For top-level tag definitions, make sure we chain the the tag decl to
|
||||
// the vardecl. This enables the AST streamer to see both X and D in the
|
||||
// following example: struct X { int A; } D;
|
||||
if (S->getParent() == 0)
|
||||
AddTopLevelDecl(New);
|
||||
|
||||
// If this has an identifier, add it to the scope stack.
|
||||
if (Name) {
|
||||
// The scope passed in may not be a decl scope. Zip up the scope tree until
|
||||
|
@ -1695,7 +1701,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,
|
|||
Name->setFETokenInfo(New);
|
||||
S->AddDecl(New);
|
||||
}
|
||||
|
||||
|
||||
return New;
|
||||
}
|
||||
|
||||
|
@ -2456,13 +2462,12 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX,
|
|||
Enum->defineElements(EltList, BestType);
|
||||
}
|
||||
|
||||
void Sema::AddTopLevelDecl(Decl *current, Decl *last) {
|
||||
void Sema::AddTopLevelDecl(Decl *current) {
|
||||
if (!current) return;
|
||||
|
||||
// If this is a top-level decl that is chained to some other (e.g. int A,B,C;)
|
||||
// remember this in the LastInGroupList list.
|
||||
if (last)
|
||||
LastInGroupList.push_back((Decl*)last);
|
||||
// remember this in the TopLevelDeclList list.
|
||||
TopLevelDeclList.push_back((Decl*)current);
|
||||
}
|
||||
|
||||
void Sema::HandleDeclAttribute(Decl *New, AttributeList *rawAttr) {
|
||||
|
|
|
@ -766,6 +766,7 @@
|
|||
08FB7793FE84155DC02AAC07 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
|
||||
compatibilityVersion = "Xcode 2.4";
|
||||
hasScannedForEncodings = 1;
|
||||
mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
|
||||
projectDirPath = "";
|
||||
|
|
|
@ -74,9 +74,9 @@ public:
|
|||
///
|
||||
void Initialize();
|
||||
|
||||
/// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
|
||||
/// action tells us to. This returns true if the EOF was encountered.
|
||||
bool ParseTopLevelDecl(DeclTy*& Result);
|
||||
/// ParseTopLevelDecl - Parse one top-level declaration. Returns true if
|
||||
/// the EOF was encountered.
|
||||
bool ParseTopLevelDecl();
|
||||
|
||||
/// Finalize - Shut down the parser.
|
||||
///
|
||||
|
|
Загрузка…
Ссылка в новой задаче