diff --git a/clang/Driver/PrintParserCallbacks.cpp b/clang/Driver/PrintParserCallbacks.cpp index fec13e39090f..2de16144d5c3 100644 --- a/clang/Driver/PrintParserCallbacks.cpp +++ b/clang/Driver/PrintParserCallbacks.cpp @@ -30,7 +30,7 @@ namespace { /// and 'Init' specifies the initializer if any. This is for things like: /// "int X = 4" or "typedef int foo". virtual DeclTy *ActOnDeclarator(Scope *S, Declarator &D, - DeclTy *LastInGroup) { + DeclTy *LastInGroup, ExprTy *AsmLabel) { llvm::cout << __FUNCTION__ << " "; if (IdentifierInfo *II = D.getIdentifier()) { llvm::cout << "'" << II->getName() << "'"; @@ -40,7 +40,7 @@ namespace { llvm::cout << "\n"; // Pass up to EmptyActions so that the symbol table is maintained right. - return MinimalAction::ActOnDeclarator(S, D, LastInGroup); + return MinimalAction::ActOnDeclarator(S, D, LastInGroup, AsmLabel); } /// ActOnPopScope - This callback is called immediately before the specified /// scope is popped and deleted. diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h index ea052559be52..71f981bd50cf 100644 --- a/clang/include/clang/AST/Attr.h +++ b/clang/include/clang/AST/Attr.h @@ -28,6 +28,7 @@ public: Alias, Aligned, Annotate, + AsmLabel, // Represent GCC asm label extension. Constructor, Deprecated, Destructor, @@ -115,6 +116,20 @@ public: static bool classof(const AnnotateAttr *A) { return true; } }; +class AsmLabelAttr : public Attr { + std::string Label; +public: + AsmLabelAttr(const std::string &L) : Attr(AsmLabel), Label(L) {} + + const std::string& getLabel() const { return Label; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() == AsmLabel; + } + static bool classof(const AsmLabelAttr *A) { return true; } +}; + class AliasAttr : public Attr { std::string Aliasee; public: diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index 2b6f713441c5..4f7937a36ce8 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -105,7 +105,12 @@ public: /// LastInGroup is non-null for cases where one declspec has multiple /// declarators on it. For example in 'int A, B', ActOnDeclarator will be /// called with LastInGroup=A when invoked for B. - virtual DeclTy *ActOnDeclarator(Scope *S, Declarator &D,DeclTy *LastInGroup) { + /// + /// AsmLabel is non-null only for top-level function declarations + /// which use the GCC asm-label extension (the expression must be a + /// constant string). + virtual DeclTy *ActOnDeclarator(Scope *S, Declarator &D, DeclTy *LastInGroup, + ExprTy *AsmLabel) { return 0; } @@ -139,7 +144,7 @@ public: virtual DeclTy *ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) { // Default to ActOnDeclarator. return ActOnStartOfFunctionDef(FnBodyScope, - ActOnDeclarator(FnBodyScope, D, 0)); + ActOnDeclarator(FnBodyScope, D, 0, 0)); } /// ActOnStartOfFunctionDef - This is called at the start of a function @@ -834,7 +839,8 @@ public: /// ActOnDeclarator - If this is a typedef declarator, we modify the /// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is /// popped. - virtual DeclTy *ActOnDeclarator(Scope *S, Declarator &D, DeclTy *LastInGroup); + virtual DeclTy *ActOnDeclarator(Scope *S, Declarator &D, DeclTy *LastInGroup, + ExprTy *AsmLabel); /// ActOnPopScope - When a scope is popped, if any typedefs are now /// out-of-scope, they are removed from the IdentifierInfo::FETokenInfo field. diff --git a/clang/lib/Parse/MinimalAction.cpp b/clang/lib/Parse/MinimalAction.cpp index cb130c3d268a..352925535dd9 100644 --- a/clang/lib/Parse/MinimalAction.cpp +++ b/clang/lib/Parse/MinimalAction.cpp @@ -63,7 +63,8 @@ MinimalAction::isTypeName(const IdentifierInfo &II, Scope *S) { /// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is /// popped. Action::DeclTy * -MinimalAction::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *LastInGroup) { +MinimalAction::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *LastInGroup, + ExprTy *AsmLabel) { IdentifierInfo *II = D.getIdentifier(); // If there is no identifier associated with this declarator, bail out. diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 81cb0ce62716..33482c5700f9 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -256,8 +256,14 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { // rest of the init-declarator-list. while (1) { // If a simple-asm-expr is present, parse it. - if (Tok.is(tok::kw_asm)) - ParseSimpleAsm(); + ExprResult AsmLabel; + if (Tok.is(tok::kw_asm)) { + AsmLabel = ParseSimpleAsm(); + if (AsmLabel.isInvalid) { + SkipUntil(tok::semi); + return 0; + } + } // If attributes are present, parse them. if (Tok.is(tok::kw___attribute)) @@ -265,13 +271,13 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { // Inform the current actions module that we just parsed this declarator. // FIXME: pass asm & attributes. - LastDeclInGroup = Actions.ActOnDeclarator(CurScope, D, LastDeclInGroup); + LastDeclInGroup = Actions.ActOnDeclarator(CurScope, D, LastDeclInGroup, + AsmLabel.Val); // Parse declarator '=' initializer. - ExprResult Init; if (Tok.is(tok::equal)) { ConsumeToken(); - Init = ParseInitializer(); + ExprResult Init = ParseInitializer(); if (Init.isInvalid) { SkipUntil(tok::semi); return 0; diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index 980105a02ce5..467cbd84a0a1 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -1222,7 +1222,7 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { ParseDeclarator(DeclaratorInfo); if (DeclaratorInfo.getIdentifier()) { DeclTy *aBlockVarDecl = Actions.ActOnDeclarator(CurScope, - DeclaratorInfo, 0); + DeclaratorInfo, 0, 0); StmtResult stmtResult = Actions.ActOnDeclStmt(aBlockVarDecl, DS.getSourceRange().getBegin(), diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index ef07d3f08ba8..9eab4fda151e 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -670,7 +670,11 @@ Parser::ExprResult Parser::ParseSimpleAsm() { ExprResult Result = ParseAsmStringLiteral(); - MatchRHSPunctuation(tok::r_paren, Loc); + if (Result.isInvalid) { + SkipUntil(tok::r_paren); + } else { + MatchRHSPunctuation(tok::r_paren, Loc); + } return Result; } diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 0fda782fcb0c..864b464d5f13 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -211,7 +211,8 @@ private: // Symbol table / Decl tracking callbacks: SemaDecl.cpp. // virtual TypeTy *isTypeName(const IdentifierInfo &II, Scope *S); - virtual DeclTy *ActOnDeclarator(Scope *S, Declarator &D, DeclTy *LastInGroup); + virtual DeclTy *ActOnDeclarator(Scope *S, Declarator &D, DeclTy *LastInGroup, + ExprTy *AsmLabel); virtual DeclTy *ActOnParamDeclarator(Scope *S, Declarator &D); virtual void ActOnParamDefaultArgument(DeclTy *param, SourceLocation EqualLoc, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e9343e39899a..64e62369e7fc 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -609,7 +609,7 @@ bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType) { } Sema::DeclTy * -Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) { +Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl, ExprTy *AsmLabel) { ScopedDecl *LastDeclarator = dyn_cast_or_null((Decl *)lastDecl); IdentifierInfo *II = D.getIdentifier(); @@ -700,6 +700,14 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) { // Handle attributes. ProcessDeclAttributes(NewFD, D); + // Handle GNU asm-label extension (encoded as an attribute). + if (Expr *E = (Expr*) AsmLabel) { + // The parser guarantees this is a string. + StringLiteral *SE = cast(E); + NewFD->addAttr(new AsmLabelAttr(std::string(SE->getStrData(), + SE->getByteLength()))); + } + // Copy the parameter declarations from the declarator D to // the function declaration NewFD, if they are available. if (D.getNumTypeObjects() > 0 && @@ -1569,7 +1577,7 @@ Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) { } return ActOnStartOfFunctionDef(FnBodyScope, - ActOnDeclarator(GlobalScope, D, 0)); + ActOnDeclarator(GlobalScope, D, 0, 0)); } Sema::DeclTy *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclTy *D) { @@ -1661,7 +1669,7 @@ ScopedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, CurContext = Context.getTranslationUnitDecl(); FunctionDecl *FD = - dyn_cast(static_cast(ActOnDeclarator(TUScope, D, 0))); + dyn_cast(static_cast(ActOnDeclarator(TUScope, D, 0, 0))); FD->setImplicit(); CurContext = PrevDC; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 9dc62dcc4ab8..d5603166d8b0 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -371,7 +371,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, if (isInstField) Member = static_cast(ActOnField(S, Loc, D, BitWidth)); else - Member = static_cast(ActOnDeclarator(S, D, LastInGroup)); + Member = static_cast(ActOnDeclarator(S, D, LastInGroup, 0)); if (!Member) return LastInGroup;