aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Driver/PrintParserCallbacks.cpp4
-rw-r--r--include/clang/AST/Attr.h15
-rw-r--r--include/clang/Parse/Action.h12
-rw-r--r--lib/Parse/MinimalAction.cpp3
-rw-r--r--lib/Parse/ParseDecl.cpp16
-rw-r--r--lib/Parse/ParseObjc.cpp2
-rw-r--r--lib/Parse/Parser.cpp6
-rw-r--r--lib/Sema/Sema.h3
-rw-r--r--lib/Sema/SemaDecl.cpp14
-rw-r--r--lib/Sema/SemaDeclCXX.cpp2
10 files changed, 59 insertions, 18 deletions
diff --git a/Driver/PrintParserCallbacks.cpp b/Driver/PrintParserCallbacks.cpp
index fec13e3909..2de16144d5 100644
--- a/Driver/PrintParserCallbacks.cpp
+++ b/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/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index ea052559be..71f981bd50 100644
--- a/include/clang/AST/Attr.h
+++ b/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/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 2b6f713441..4f7937a36c 100644
--- a/include/clang/Parse/Action.h
+++ b/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/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index cb130c3d26..352925535d 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/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/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 81cb0ce627..33482c5700 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/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/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 980105a02c..467cbd84a0 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/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/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index ef07d3f08b..9eab4fda15 100644
--- a/lib/Parse/Parser.cpp
+++ b/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/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 0fda782fcb..864b464d5f 100644
--- a/lib/Sema/Sema.h
+++ b/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/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index e9343e3989..64e62369e7 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/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<ScopedDecl>((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<StringLiteral>(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<FunctionDecl>(static_cast<Decl*>(ActOnDeclarator(TUScope, D, 0)));
+ dyn_cast<FunctionDecl>(static_cast<Decl*>(ActOnDeclarator(TUScope, D, 0, 0)));
FD->setImplicit();
CurContext = PrevDC;
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 9dc62dcc4a..d5603166d8 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -371,7 +371,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
if (isInstField)
Member = static_cast<Decl*>(ActOnField(S, Loc, D, BitWidth));
else
- Member = static_cast<Decl*>(ActOnDeclarator(S, D, LastInGroup));
+ Member = static_cast<Decl*>(ActOnDeclarator(S, D, LastInGroup, 0));
if (!Member) return LastInGroup;