summaryrefslogtreecommitdiffstats
path: root/clang/include/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang/include/clang')
-rw-r--r--clang/include/clang/Basic/DiagnosticKinds.def2
-rw-r--r--clang/include/clang/Parse/Action.h66
-rw-r--r--clang/include/clang/Parse/DeclSpec.h41
-rw-r--r--clang/include/clang/Parse/Parser.h75
4 files changed, 174 insertions, 10 deletions
diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def
index 0067061b014..fa3918205c6 100644
--- a/clang/include/clang/Basic/DiagnosticKinds.def
+++ b/clang/include/clang/Basic/DiagnosticKinds.def
@@ -550,6 +550,8 @@ DIAG(warn_property_type, WARNING,
"property type '%0' does not match property type inherited from '%1'")
/// C++ parser diagnostics
+DIAG(err_expected_unqualified_id, ERROR,
+ "expected unqualified-id")
DIAG(err_no_declarators, ERROR,
"declaration does not declare anything")
DIAG(err_func_def_no_params, ERROR,
diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h
index 698feff0b94..038c8583f81 100644
--- a/clang/include/clang/Parse/Action.h
+++ b/clang/include/clang/Parse/Action.h
@@ -22,6 +22,7 @@ namespace clang {
// Semantic.
class DeclSpec;
class ObjCDeclSpec;
+ class CXXScopeSpec;
class Declarator;
class AttributeList;
struct FieldDeclarator;
@@ -60,6 +61,7 @@ public:
typedef void AttrTy;
typedef void BaseTy;
typedef void MemInitTy;
+ typedef void CXXScopeTy;
/// ActionResult - This structure is used while parsing/acting on expressions,
/// stmts, etc. It encapsulates both the object returned by the action, plus
@@ -103,11 +105,54 @@ public:
/// isTypeName - Return non-null if the specified identifier is a typedef name
/// in the current scope.
- virtual TypeTy *isTypeName(const IdentifierInfo &II, Scope *S) = 0;
+ /// An optional CXXScopeSpec can be passed to indicate the C++ scope (class or
+ /// namespace) that the identifier must be a member of.
+ /// i.e. for "foo::bar", 'II' will be "bar" and 'SS' will be "foo::".
+ virtual TypeTy *isTypeName(const IdentifierInfo &II, Scope *S,
+ const CXXScopeSpec *SS = 0) = 0;
/// isCurrentClassName - Return true if the specified name is the
/// name of the innermost C++ class type currently being defined.
- virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S) = 0;
+ virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
+ const CXXScopeSpec *SS = 0) = 0;
+
+ /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
+ /// global scope ('::').
+ virtual CXXScopeTy *ActOnCXXGlobalScopeSpecifier(Scope *S,
+ SourceLocation CCLoc) {
+ return 0;
+ }
+
+ /// ActOnCXXNestedNameSpecifier - Called during parsing of a
+ /// nested-name-specifier. e.g. for "foo::bar::" we parsed "foo::" and now
+ /// we want to resolve "bar::". 'SS' is empty or the previously parsed
+ /// nested-name part ("foo::"), 'IdLoc' is the source location of 'bar',
+ /// 'CCLoc' is the location of '::' and 'II' is the identifier for 'bar'.
+ /// Returns a CXXScopeTy* object representing the C++ scope.
+ virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S,
+ const CXXScopeSpec &SS,
+ SourceLocation IdLoc,
+ SourceLocation CCLoc,
+ const IdentifierInfo &II) {
+ return 0;
+ }
+
+ /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
+ /// scope or nested-name-specifier) is parsed, part of a declarator-id.
+ /// After this method is called, according to [C++ 3.4.3p3], names should be
+ /// looked up in the declarator-id's scope, until the declarator is parsed and
+ /// ActOnCXXExitDeclaratorScope is called.
+ /// The 'SS' should be a non-empty valid CXXScopeSpec.
+ virtual void ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
+ }
+
+ /// ActOnCXXExitDeclaratorScope - Called when a declarator that previously
+ /// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same
+ /// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well.
+ /// Used to indicate that names should revert to being looked up in the
+ /// defining scope.
+ virtual void ActOnCXXExitDeclaratorScope(const CXXScopeSpec &SS) {
+ }
/// getTypeAsString - Returns a string that describes the given
/// type. This callback is used in C++ to form identifiers for
@@ -227,8 +272,9 @@ public:
TK_Definition // Definition of a tag: 'struct foo { int X; } Y;'
};
virtual DeclTy *ActOnTag(Scope *S, unsigned TagType, TagKind TK,
- SourceLocation KWLoc, IdentifierInfo *Name,
- SourceLocation NameLoc, AttributeList *Attr) {
+ SourceLocation KWLoc, const CXXScopeSpec &SS,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ AttributeList *Attr) {
// TagType is an instance of DeclSpec::TST, indicating what kind of tag this
// is (struct/union/enum/class).
return 0;
@@ -413,9 +459,13 @@ public:
/// ActOnIdentifierExpr - Parse an identifier in expression context.
/// 'HasTrailingLParen' indicates whether or not the identifier has a '('
/// token immediately after it.
+ /// An optional CXXScopeSpec can be passed to indicate the C++ scope (class or
+ /// namespace) that the identifier must be a member of.
+ /// i.e. for "foo::bar", 'II' will be "bar" and 'SS' will be "foo::".
virtual ExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
IdentifierInfo &II,
- bool HasTrailingLParen) {
+ bool HasTrailingLParen,
+ const CXXScopeSpec *SS = 0) {
return 0;
}
@@ -968,11 +1018,13 @@ public:
/// isTypeName - This looks at the IdentifierInfo::FETokenInfo field to
/// determine whether the name is a typedef or not in this scope.
- virtual TypeTy *isTypeName(const IdentifierInfo &II, Scope *S);
+ virtual TypeTy *isTypeName(const IdentifierInfo &II, Scope *S,
+ const CXXScopeSpec *SS);
/// isCurrentClassName - Always returns false, because MinimalAction
/// does not support C++ classes with constructors.
- virtual bool isCurrentClassName(const IdentifierInfo& II, Scope *S);
+ virtual bool isCurrentClassName(const IdentifierInfo& II, Scope *S,
+ const CXXScopeSpec *SS);
/// ActOnDeclarator - If this is a typedef declarator, we modify the
/// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is
diff --git a/clang/include/clang/Parse/DeclSpec.h b/clang/include/clang/Parse/DeclSpec.h
index 76e3e7ba892..94bd839a014 100644
--- a/clang/include/clang/Parse/DeclSpec.h
+++ b/clang/include/clang/Parse/DeclSpec.h
@@ -385,6 +385,40 @@ private:
IdentifierInfo *GetterName; // getter name of NULL if no getter
IdentifierInfo *SetterName; // setter name of NULL if no setter
};
+
+/// CXXScopeSpec - Represents a C++ nested-name-specifier or a global scope
+/// specifier.
+class CXXScopeSpec {
+ SourceRange Range;
+ Action::CXXScopeTy *ScopeRep;
+
+public:
+ CXXScopeSpec() : ScopeRep(0) {}
+
+ const SourceRange &getRange() const { return Range; }
+ void setRange(const SourceRange &R) { Range = R; }
+ void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); }
+ void setEndLoc(SourceLocation Loc) { Range.setEnd(Loc); }
+ SourceLocation getBeginLoc() const { return Range.getBegin(); }
+ SourceLocation getEndLoc() const { return Range.getEnd(); }
+
+ Action::CXXScopeTy *getScopeRep() const { return ScopeRep; }
+ void setScopeRep(Action::CXXScopeTy *S) { ScopeRep = S; }
+
+ bool isEmpty() const { return !Range.isValid(); }
+ bool isNotEmpty() const { return !isEmpty(); }
+
+ /// isInvalid - An error occured during parsing of the scope specifier.
+ bool isInvalid() const { return isNotEmpty() && ScopeRep == 0; }
+
+ /// isSet - A scope specifier was resolved to a valid C++ scope.
+ bool isSet() const { return getScopeRep() != 0; }
+
+ void clear() {
+ Range = SourceRange();
+ ScopeRep = 0;
+ }
+};
/// DeclaratorChunk - One instance of this struct is used for each type in a
/// declarator that is parsed.
@@ -590,6 +624,7 @@ struct DeclaratorChunk {
/// stack, not objects that are allocated in large quantities on the heap.
class Declarator {
const DeclSpec &DS;
+ CXXScopeSpec SS;
IdentifierInfo *Identifier;
SourceLocation IdentifierLoc;
@@ -667,6 +702,11 @@ public:
/// be shared or when in error recovery etc.
DeclSpec &getMutableDeclSpec() { return const_cast<DeclSpec &>(DS); }
+ /// getCXXScopeSpec - Return the C++ scope specifier (global scope or
+ /// nested-name-specifier) that is part of the declarator-id.
+ const CXXScopeSpec &getCXXScopeSpec() const { return SS; }
+ CXXScopeSpec &getCXXScopeSpec() { return SS; }
+
TheContext getContext() const { return Context; }
DeclaratorKind getKind() const { return Kind; }
@@ -675,6 +715,7 @@ public:
/// clear - Reset the contents of this Declarator.
void clear() {
+ SS.clear();
Identifier = 0;
IdentifierLoc = SourceLocation();
Kind = DK_Abstract;
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index f9b233ca0eb..c7558dbd579 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -16,6 +16,7 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/Action.h"
+#include "clang/Parse/DeclSpec.h"
#include <stack>
namespace clang {
@@ -75,6 +76,7 @@ public:
typedef Action::TypeTy TypeTy;
typedef Action::BaseTy BaseTy;
typedef Action::MemInitTy MemInitTy;
+ typedef Action::CXXScopeTy CXXScopeTy;
// Parsing methods.
@@ -114,7 +116,35 @@ private:
return Tok.getKind() == tok::string_literal ||
Tok.getKind() == tok::wide_string_literal;
}
+
+ /// isTokenCXXScopeSpecifier - True if this token is '::', or identifier with
+ /// '::' as next token, or a 'C++ scope annotation' token.
+ /// When not in C++, always returns false.
+ ///
+ bool isTokenCXXScopeSpecifier() {
+ return getLang().CPlusPlus &&
+ (Tok.is(tok::coloncolon) ||
+ Tok.is(tok::annot_cxxscope) ||
+ (Tok.is(tok::identifier) && NextToken().is(tok::coloncolon)));
+ }
+ /// isTokenUnqualifiedId - True if token is the start of C++ unqualified-id
+ /// or an identifier in C.
+ ///
+ /// unqualified-id:
+ /// identifier
+ /// [C++] operator-function-id
+ /// [C++] conversion-function-id
+ /// [C++] '~' class-name
+ /// [C++] template-id [TODO]
+ ///
+ bool isTokenUnqualifiedId() const {
+ return Tok.is(tok::identifier) || // identifier or template-id
+ Tok.is(tok::kw_operator) || // operator/conversion-function-id or
+ // template-id
+ (Tok.is(tok::tilde) && getLang().CPlusPlus); // '~' class-name
+ }
+
/// ConsumeToken - Consume the current 'peek token' and lex the next one.
/// This does not work with all kinds of tokens: strings and specific other
/// tokens must be consumed with custom methods below. This returns the
@@ -215,6 +245,20 @@ private:
return PP.LookAhead(0);
}
+ /// TryAnnotateTypeOrScopeToken - If the current token position is on a
+ /// typename (possibly qualified in C++) or a C++ scope specifier not followed
+ /// by a typename, TryAnnotateTypeOrScopeToken will replace one or more tokens
+ /// with a single annotation token representing the typename or C++ scope
+ /// respectively.
+ /// This simplifies handling of C++ scope specifiers and allows efficient
+ /// backtracking without the need to re-parse and resolve nested-names and
+ /// typenames.
+ void TryAnnotateTypeOrScopeToken();
+
+ /// TryAnnotateScopeToken - Like TryAnnotateTypeOrScopeToken but only
+ /// annotates C++ scope specifiers.
+ void TryAnnotateScopeToken();
+
/// TentativeParsingAction - An object that is used as a kind of "tentative
/// parsing transaction". It gets instantiated to mark the token position and
/// after the token consumption is done, Commit() or Revert() is called to
@@ -449,6 +493,11 @@ private:
return ParseParenExpression(Op, CastTy, RParenLoc);
}
ExprResult ParseStringLiteralExpression();
+
+ //===--------------------------------------------------------------------===//
+ // C++ Expressions
+ ExprResult ParseCXXIdExpression();
+ void ParseCXXScopeSpecifier(CXXScopeSpec &SS);
//===--------------------------------------------------------------------===//
// C++ 5.2p1: C++ Casts
@@ -583,8 +632,8 @@ private:
void ParseStructDeclaration(DeclSpec &DS,
llvm::SmallVectorImpl<FieldDeclarator> &Fields);
- bool isDeclarationSpecifier() const;
- bool isTypeSpecifierQualifier() const;
+ bool isDeclarationSpecifier();
+ bool isTypeSpecifierQualifier();
bool isTypeQualifier() const;
/// isDeclarationStatement - Disambiguates between a declaration or an
@@ -700,6 +749,26 @@ private:
TypeTy *ParseTypeName();
AttributeList *ParseAttributes();
void ParseTypeofSpecifier(DeclSpec &DS);
+
+ /// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to
+ /// enter a new C++ declarator scope and exit it when the function is
+ /// finished.
+ class DeclaratorScopeObj {
+ CXXScopeSpec &SS;
+ Parser &P;
+ public:
+ DeclaratorScopeObj(Parser &p, CXXScopeSpec &ss) : P(p), SS(ss) {}
+
+ void EnterDeclaratorScope() {
+ if (SS.isSet())
+ P.Actions.ActOnCXXEnterDeclaratorScope(P.CurScope, SS);
+ }
+
+ ~DeclaratorScopeObj() {
+ if (SS.isSet())
+ P.Actions.ActOnCXXExitDeclaratorScope(SS);
+ }
+ };
/// ParseDeclarator - Parse and verify a newly-initialized declarator.
void ParseDeclarator(Declarator &D);
@@ -722,7 +791,7 @@ private:
//===--------------------------------------------------------------------===//
// C++ 9: classes [class] and C structs/unions.
- TypeTy *ParseClassName();
+ TypeTy *ParseClassName(const CXXScopeSpec *SS = 0);
void ParseClassSpecifier(DeclSpec &DS);
void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
DeclTy *TagDecl);
OpenPOWER on IntegriCloud