aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2009-10-14 18:03:49 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2009-10-14 18:03:49 +0000
commit4c8b24812ddcd1dedaca343a6d4e76f91f398981 (patch)
tree137ebebcae16fb0ce7ab4af456992bbd8d22fced /lib/Parse
parent5362a71c02e7d448a8ce98cf00c47e353fba5d04 (diff)
downloadsrc-4c8b24812ddcd1dedaca343a6d4e76f91f398981.tar.gz
src-4c8b24812ddcd1dedaca343a6d4e76f91f398981.zip
Update clang to r84119.vendor/clang/clang-r84119
Notes
Notes: svn path=/vendor/clang/dist/; revision=198092 svn path=/vendor/clang/clang-84119/; revision=198093; tag=vendor/clang/clang-r84119
Diffstat (limited to 'lib/Parse')
-rw-r--r--lib/Parse/AttributeList.cpp20
-rw-r--r--lib/Parse/CMakeLists.txt4
-rw-r--r--lib/Parse/DeclSpec.cpp186
-rw-r--r--lib/Parse/ExtensionRAIIObject.h2
-rw-r--r--lib/Parse/MinimalAction.cpp70
-rw-r--r--lib/Parse/ParseCXXInlineMethods.cpp44
-rw-r--r--lib/Parse/ParseDecl.cpp858
-rw-r--r--lib/Parse/ParseDeclCXX.cpp533
-rw-r--r--lib/Parse/ParseExpr.cpp255
-rw-r--r--lib/Parse/ParseExprCXX.cpp220
-rw-r--r--lib/Parse/ParseInit.cpp40
-rw-r--r--lib/Parse/ParseObjc.cpp301
-rw-r--r--lib/Parse/ParsePragma.cpp65
-rw-r--r--lib/Parse/ParsePragma.h18
-rw-r--r--lib/Parse/ParseStmt.cpp109
-rw-r--r--lib/Parse/ParseTemplate.cpp221
-rw-r--r--lib/Parse/ParseTentative.cpp24
-rw-r--r--lib/Parse/Parser.cpp137
18 files changed, 1883 insertions, 1224 deletions
diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp
index 5ee668a31723..2ee41bc3eb8d 100644
--- a/lib/Parse/AttributeList.cpp
+++ b/lib/Parse/AttributeList.cpp
@@ -21,7 +21,7 @@ AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc,
AttributeList *n, bool declspec)
: AttrName(aName), AttrLoc(aLoc), ParmName(pName), ParmLoc(pLoc),
NumArgs(numArgs), Next(n), DeclspecAttribute(declspec) {
-
+
if (numArgs == 0)
Args = 0;
else {
@@ -32,12 +32,12 @@ AttributeList::AttributeList(IdentifierInfo *aName, SourceLocation aLoc,
AttributeList::~AttributeList() {
if (Args) {
- // FIXME: before we delete the vector, we need to make sure the Expr's
+ // FIXME: before we delete the vector, we need to make sure the Expr's
// have been deleted. Since ActionBase::ExprTy is "void", we are dependent
// on the actions module for actually freeing the memory. The specific
- // hooks are ActOnDeclarator, ActOnTypeName, ActOnParamDeclaratorType,
- // ParseField, ParseTag. Once these routines have freed the expression,
- // they should zero out the Args slot (to indicate the memory has been
+ // hooks are ActOnDeclarator, ActOnTypeName, ActOnParamDeclaratorType,
+ // ParseField, ParseTag. Once these routines have freed the expression,
+ // they should zero out the Args slot (to indicate the memory has been
// freed). If any element of the vector is non-null, we should assert.
delete [] Args;
}
@@ -54,7 +54,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
Str += 2;
Len -= 4;
}
-
+
// FIXME: Hand generating this is neither smart nor efficient.
switch (Len) {
case 4:
@@ -69,7 +69,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
break;
case 6:
if (!memcmp(Str, "packed", 6)) return AT_packed;
- if (!memcmp(Str, "malloc", 6)) return IgnoredAttribute; // FIXME: noalias.
+ if (!memcmp(Str, "malloc", 6)) return AT_malloc;
if (!memcmp(Str, "format", 6)) return AT_format;
if (!memcmp(Str, "unused", 6)) return AT_unused;
if (!memcmp(Str, "blocks", 6)) return AT_blocks;
@@ -103,7 +103,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
if (!memcmp(Str, "deprecated", 10)) return AT_deprecated;
if (!memcmp(Str, "visibility", 10)) return AT_visibility;
if (!memcmp(Str, "destructor", 10)) return AT_destructor;
- if (!memcmp(Str, "format_arg", 10)) return AT_format_arg;
+ if (!memcmp(Str, "format_arg", 10)) return AT_format_arg;
if (!memcmp(Str, "gnu_inline", 10)) return AT_gnu_inline;
break;
case 11:
@@ -136,13 +136,13 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
case 19:
if (!memcmp(Str, "ns_returns_retained", 19)) return AT_ns_returns_retained;
if (!memcmp(Str, "cf_returns_retained", 19)) return AT_cf_returns_retained;
- break;
+ break;
case 20:
if (!memcmp(Str, "reqd_work_group_size", 20)) return AT_reqd_wg_size;
case 22:
if (!memcmp(Str, "no_instrument_function", 22))
return AT_no_instrument_function;
break;
- }
+ }
return UnknownAttribute;
}
diff --git a/lib/Parse/CMakeLists.txt b/lib/Parse/CMakeLists.txt
index 8fb7cd23b89a..bec1c6e10e8b 100644
--- a/lib/Parse/CMakeLists.txt
+++ b/lib/Parse/CMakeLists.txt
@@ -12,10 +12,10 @@ add_clang_library(clangParse
ParseInit.cpp
ParseObjc.cpp
ParsePragma.cpp
- Parser.cpp
ParseStmt.cpp
- ParseTentative.cpp
ParseTemplate.cpp
+ ParseTentative.cpp
+ Parser.cpp
)
add_dependencies(clangParse ClangDiagnosticParse)
diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp
index 8b3b2851c1e0..b8422aad5a84 100644
--- a/lib/Parse/DeclSpec.cpp
+++ b/lib/Parse/DeclSpec.cpp
@@ -16,6 +16,7 @@
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/LangOptions.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/ErrorHandling.h"
#include <cstring>
using namespace clang;
@@ -38,11 +39,13 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
ActionBase::TypeTy **Exceptions,
SourceRange *ExceptionRanges,
unsigned NumExceptions,
- SourceLocation Loc,
+ SourceLocation LPLoc,
+ SourceLocation RPLoc,
Declarator &TheDeclarator) {
DeclaratorChunk I;
I.Kind = Function;
- I.Loc = Loc;
+ I.Loc = LPLoc;
+ I.EndLoc = RPLoc;
I.Fun.hasPrototype = hasProto;
I.Fun.isVariadic = isVariadic;
I.Fun.EllipsisLoc = EllipsisLoc.getRawEncoding();
@@ -62,7 +65,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
// parameter list there (in an effort to avoid new/delete traffic). If it
// is already used (consider a function returning a function pointer) or too
// small (function taking too many arguments), go to the heap.
- if (!TheDeclarator.InlineParamsUsed &&
+ if (!TheDeclarator.InlineParamsUsed &&
NumArgs <= llvm::array_lengthof(TheDeclarator.InlineParams)) {
I.Fun.ArgInfo = TheDeclarator.InlineParams;
I.Fun.DeleteArgInfo = false;
@@ -95,18 +98,26 @@ unsigned DeclSpec::getParsedSpecifiers() const {
if (TypeQualifiers != TQ_unspecified)
Res |= PQ_TypeQualifier;
-
+
if (hasTypeSpecifier())
Res |= PQ_TypeSpecifier;
-
+
if (FS_inline_specified || FS_virtual_specified || FS_explicit_specified)
Res |= PQ_FunctionSpecifier;
return Res;
}
+template <class T> static bool BadSpecifier(T TNew, T TPrev,
+ const char *&PrevSpec,
+ unsigned &DiagID) {
+ PrevSpec = DeclSpec::getSpecifierName(TPrev);
+ DiagID = (TNew == TPrev ? diag::ext_duplicate_declspec
+ : diag::err_invalid_decl_spec_combination);
+ return true;
+}
+
const char *DeclSpec::getSpecifierName(DeclSpec::SCS S) {
switch (S) {
- default: assert(0 && "Unknown typespec!");
case DeclSpec::SCS_unspecified: return "unspecified";
case DeclSpec::SCS_typedef: return "typedef";
case DeclSpec::SCS_extern: return "extern";
@@ -116,49 +127,46 @@ const char *DeclSpec::getSpecifierName(DeclSpec::SCS S) {
case DeclSpec::SCS_private_extern: return "__private_extern__";
case DeclSpec::SCS_mutable: return "mutable";
}
+ llvm::llvm_unreachable("Unknown typespec!");
}
-bool DeclSpec::BadSpecifier(SCS S, const char *&PrevSpec) {
- PrevSpec = getSpecifierName(S);
- return true;
-}
-
-bool DeclSpec::BadSpecifier(TSW W, const char *&PrevSpec) {
+const char *DeclSpec::getSpecifierName(TSW W) {
switch (W) {
- case TSW_unspecified: PrevSpec = "unspecified"; break;
- case TSW_short: PrevSpec = "short"; break;
- case TSW_long: PrevSpec = "long"; break;
- case TSW_longlong: PrevSpec = "long long"; break;
+ case TSW_unspecified: return "unspecified";
+ case TSW_short: return "short";
+ case TSW_long: return "long";
+ case TSW_longlong: return "long long";
}
- return true;
+ llvm::llvm_unreachable("Unknown typespec!");
}
-bool DeclSpec::BadSpecifier(TSC C, const char *&PrevSpec) {
+const char *DeclSpec::getSpecifierName(TSC C) {
switch (C) {
- case TSC_unspecified: PrevSpec = "unspecified"; break;
- case TSC_imaginary: PrevSpec = "imaginary"; break;
- case TSC_complex: PrevSpec = "complex"; break;
+ case TSC_unspecified: return "unspecified";
+ case TSC_imaginary: return "imaginary";
+ case TSC_complex: return "complex";
}
- return true;
+ llvm::llvm_unreachable("Unknown typespec!");
}
-bool DeclSpec::BadSpecifier(TSS S, const char *&PrevSpec) {
+const char *DeclSpec::getSpecifierName(TSS S) {
switch (S) {
- case TSS_unspecified: PrevSpec = "unspecified"; break;
- case TSS_signed: PrevSpec = "signed"; break;
- case TSS_unsigned: PrevSpec = "unsigned"; break;
+ case TSS_unspecified: return "unspecified";
+ case TSS_signed: return "signed";
+ case TSS_unsigned: return "unsigned";
}
- return true;
+ llvm::llvm_unreachable("Unknown typespec!");
}
const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
switch (T) {
- default: assert(0 && "Unknown typespec!");
case DeclSpec::TST_unspecified: return "unspecified";
case DeclSpec::TST_void: return "void";
case DeclSpec::TST_char: return "char";
case DeclSpec::TST_wchar: return "wchar_t";
+ case DeclSpec::TST_char16: return "char16_t";
+ case DeclSpec::TST_char32: return "char32_t";
case DeclSpec::TST_int: return "int";
case DeclSpec::TST_float: return "float";
case DeclSpec::TST_double: return "double";
@@ -173,39 +181,40 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) {
case DeclSpec::TST_typename: return "type-name";
case DeclSpec::TST_typeofType:
case DeclSpec::TST_typeofExpr: return "typeof";
- case DeclSpec::TST_auto: return "auto";
+ case DeclSpec::TST_auto: return "auto";
+ case DeclSpec::TST_decltype: return "(decltype)";
+ case DeclSpec::TST_error: return "(error)";
}
+ llvm::llvm_unreachable("Unknown typespec!");
}
-bool DeclSpec::BadSpecifier(TST T, const char *&PrevSpec) {
- PrevSpec = getSpecifierName(T);
- return true;
-}
-
-bool DeclSpec::BadSpecifier(TQ T, const char *&PrevSpec) {
+const char *DeclSpec::getSpecifierName(TQ T) {
switch (T) {
- case DeclSpec::TQ_unspecified: PrevSpec = "unspecified"; break;
- case DeclSpec::TQ_const: PrevSpec = "const"; break;
- case DeclSpec::TQ_restrict: PrevSpec = "restrict"; break;
- case DeclSpec::TQ_volatile: PrevSpec = "volatile"; break;
+ case DeclSpec::TQ_unspecified: return "unspecified";
+ case DeclSpec::TQ_const: return "const";
+ case DeclSpec::TQ_restrict: return "restrict";
+ case DeclSpec::TQ_volatile: return "volatile";
}
- return true;
+ llvm::llvm_unreachable("Unknown typespec!");
}
bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc,
- const char *&PrevSpec) {
+ const char *&PrevSpec,
+ unsigned &DiagID) {
if (StorageClassSpec != SCS_unspecified)
- return BadSpecifier((SCS)StorageClassSpec, PrevSpec);
+ return BadSpecifier(S, (SCS)StorageClassSpec, PrevSpec, DiagID);
StorageClassSpec = S;
StorageClassSpecLoc = Loc;
assert((unsigned)S == StorageClassSpec && "SCS constants overflow bitfield");
return false;
}
-bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc,
- const char *&PrevSpec) {
+bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc,
+ const char *&PrevSpec,
+ unsigned &DiagID) {
if (SCS_thread_specified) {
PrevSpec = "__thread";
+ DiagID = diag::ext_duplicate_declspec;
return true;
}
SCS_thread_specified = true;
@@ -218,39 +227,46 @@ bool DeclSpec::SetStorageClassSpecThread(SourceLocation Loc,
/// and ignore the request if invalid (e.g. "extern" then "auto" is
/// specified).
bool DeclSpec::SetTypeSpecWidth(TSW W, SourceLocation Loc,
- const char *&PrevSpec) {
+ const char *&PrevSpec,
+ unsigned &DiagID) {
if (TypeSpecWidth != TSW_unspecified &&
// Allow turning long -> long long.
(W != TSW_longlong || TypeSpecWidth != TSW_long))
- return BadSpecifier((TSW)TypeSpecWidth, PrevSpec);
+ return BadSpecifier(W, (TSW)TypeSpecWidth, PrevSpec, DiagID);
TypeSpecWidth = W;
TSWLoc = Loc;
return false;
}
-bool DeclSpec::SetTypeSpecComplex(TSC C, SourceLocation Loc,
- const char *&PrevSpec) {
+bool DeclSpec::SetTypeSpecComplex(TSC C, SourceLocation Loc,
+ const char *&PrevSpec,
+ unsigned &DiagID) {
if (TypeSpecComplex != TSC_unspecified)
- return BadSpecifier((TSC)TypeSpecComplex, PrevSpec);
+ return BadSpecifier(C, (TSC)TypeSpecComplex, PrevSpec, DiagID);
TypeSpecComplex = C;
TSCLoc = Loc;
return false;
}
-bool DeclSpec::SetTypeSpecSign(TSS S, SourceLocation Loc,
- const char *&PrevSpec) {
+bool DeclSpec::SetTypeSpecSign(TSS S, SourceLocation Loc,
+ const char *&PrevSpec,
+ unsigned &DiagID) {
if (TypeSpecSign != TSS_unspecified)
- return BadSpecifier((TSS)TypeSpecSign, PrevSpec);
+ return BadSpecifier(S, (TSS)TypeSpecSign, PrevSpec, DiagID);
TypeSpecSign = S;
TSSLoc = Loc;
return false;
}
bool DeclSpec::SetTypeSpecType(TST T, SourceLocation Loc,
- const char *&PrevSpec, void *Rep,
- bool Owned) {
- if (TypeSpecType != TST_unspecified)
- return BadSpecifier((TST)TypeSpecType, PrevSpec);
+ const char *&PrevSpec,
+ unsigned &DiagID,
+ void *Rep, bool Owned) {
+ if (TypeSpecType != TST_unspecified) {
+ PrevSpec = DeclSpec::getSpecifierName((TST) TypeSpecType);
+ DiagID = diag::err_invalid_decl_spec_combination;
+ return true;
+ }
TypeSpecType = T;
TypeRep = Rep;
TSTLoc = Loc;
@@ -266,12 +282,12 @@ bool DeclSpec::SetTypeSpecError() {
}
bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
- const LangOptions &Lang) {
+ unsigned &DiagID, const LangOptions &Lang) {
// Duplicates turn into warnings pre-C99.
if ((TypeQualifiers & T) && !Lang.C99)
- return BadSpecifier(T, PrevSpec);
+ return BadSpecifier(T, T, PrevSpec, DiagID);
TypeQualifiers |= T;
-
+
switch (T) {
default: assert(0 && "Unknown type qualifier!");
case TQ_const: TQ_constLoc = Loc; break;
@@ -281,38 +297,56 @@ bool DeclSpec::SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec,
return false;
}
-bool DeclSpec::SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec){
+bool DeclSpec::SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
// 'inline inline' is ok.
FS_inline_specified = true;
FS_inlineLoc = Loc;
return false;
}
-bool DeclSpec::SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec){
+bool DeclSpec::SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
// 'virtual virtual' is ok.
FS_virtual_specified = true;
FS_virtualLoc = Loc;
return false;
}
-bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec){
+bool DeclSpec::SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
// 'explicit explicit' is ok.
FS_explicit_specified = true;
FS_explicitLoc = Loc;
return false;
}
-bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec) {
+bool DeclSpec::SetFriendSpec(SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID) {
if (Friend_specified) {
PrevSpec = "friend";
+ DiagID = diag::ext_duplicate_declspec;
return true;
}
-
+
Friend_specified = true;
FriendLoc = Loc;
return false;
}
+void DeclSpec::setProtocolQualifiers(const ActionBase::DeclPtrTy *Protos,
+ unsigned NP,
+ SourceLocation *ProtoLocs,
+ SourceLocation LAngleLoc) {
+ if (NP == 0) return;
+ ProtocolQualifiers = new ActionBase::DeclPtrTy[NP];
+ ProtocolLocs = new SourceLocation[NP];
+ memcpy((void*)ProtocolQualifiers, Protos, sizeof(ActionBase::DeclPtrTy)*NP);
+ memcpy(ProtocolLocs, ProtoLocs, sizeof(SourceLocation)*NP);
+ NumProtocolQualifiers = NP;
+ ProtocolLAngleLoc = LAngleLoc;
+}
+
/// Finish - This does final analysis of the declspec, rejecting things like
/// "_Imaginary" (lacking an FP type). This returns a diagnostic to issue or
/// diag::NUM_DIAGNOSTICS if there is no error. After calling this method,
@@ -359,7 +393,7 @@ void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
}
break;
}
-
+
// TODO: if the implementation does not implement _Complex or _Imaginary,
// disallow their use. Need information about the backend.
if (TypeSpecComplex != TSC_unspecified) {
@@ -379,10 +413,28 @@ void DeclSpec::Finish(Diagnostic &D, Preprocessor &PP) {
}
}
+ // C++ [class.friend]p6:
+ // No storage-class-specifier shall appear in the decl-specifier-seq
+ // of a friend declaration.
+ if (isFriendSpecified() && getStorageClassSpec()) {
+ DeclSpec::SCS SC = getStorageClassSpec();
+ const char *SpecName = getSpecifierName(SC);
+
+ SourceLocation SCLoc = getStorageClassSpecLoc();
+ SourceLocation SCEndLoc = SCLoc.getFileLocWithOffset(strlen(SpecName));
+
+ Diag(D, SCLoc, SrcMgr, diag::err_friend_storage_spec)
+ << SpecName
+ << CodeModificationHint::CreateRemoval(SourceRange(SCLoc, SCEndLoc));
+
+ ClearStorageClassSpecs();
+ }
+
+
// Okay, now we can infer the real type.
-
+
// TODO: return "auto function" and other bad things based on the real type.
-
+
// 'data definition has no type or storage class'?
}
diff --git a/lib/Parse/ExtensionRAIIObject.h b/lib/Parse/ExtensionRAIIObject.h
index 2b2bd3b21648..cc7c8e21705c 100644
--- a/lib/Parse/ExtensionRAIIObject.h
+++ b/lib/Parse/ExtensionRAIIObject.h
@@ -30,7 +30,7 @@ namespace clang {
ExtensionRAIIObject(Diagnostic &diags) : Diags(diags) {
Diags.IncrementAllExtensionsSilenced();
}
-
+
~ExtensionRAIIObject() {
Diags.DecrementAllExtensionsSilenced();
}
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index 648e2da54bfe..71b22cad6f62 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -34,7 +34,7 @@ Action::DeclPtrTy Action::ActOnUsingDirective(Scope *CurScope,
SourceLocation IdentLoc,
IdentifierInfo *NamespcName,
AttributeList *AttrList) {
-
+
// FIXME: Parser seems to assume that Action::ActOn* takes ownership over
// passed AttributeList, however other actions don't free it, is it
// temporary state or bug?
@@ -44,14 +44,15 @@ Action::DeclPtrTy Action::ActOnUsingDirective(Scope *CurScope,
// Defined out-of-line here because of dependecy on AttributeList
Action::DeclPtrTy Action::ActOnUsingDeclaration(Scope *CurScope,
- SourceLocation UsingLoc,
- const CXXScopeSpec &SS,
- SourceLocation IdentLoc,
- IdentifierInfo *TargetName,
- OverloadedOperatorKind Op,
- AttributeList *AttrList,
- bool IsTypeName) {
-
+ AccessSpecifier AS,
+ SourceLocation UsingLoc,
+ const CXXScopeSpec &SS,
+ SourceLocation IdentLoc,
+ IdentifierInfo *TargetName,
+ OverloadedOperatorKind Op,
+ AttributeList *AttrList,
+ bool IsTypeName) {
+
// FIXME: Parser seems to assume that Action::ActOn* takes ownership over
// passed AttributeList, however other actions don't free it, is it
// temporary state or bug?
@@ -66,11 +67,11 @@ void PrettyStackTraceActionsDecl::print(llvm::raw_ostream &OS) const {
OS << ": ";
}
OS << Message;
-
+
std::string Name = Actions.getDeclName(TheDecl);
if (!Name.empty())
OS << " '" << Name << '\'';
-
+
OS << '\n';
}
@@ -80,7 +81,7 @@ namespace {
struct TypeNameInfo {
TypeNameInfo *Prev;
bool isTypeName;
-
+
TypeNameInfo(bool istypename, TypeNameInfo *prev) {
isTypeName = istypename;
Prev = prev;
@@ -89,13 +90,13 @@ namespace {
struct TypeNameInfoTable {
llvm::RecyclingAllocator<llvm::BumpPtrAllocator, TypeNameInfo> Allocator;
-
+
void AddEntry(bool isTypename, IdentifierInfo *II) {
TypeNameInfo *TI = Allocator.Allocate<TypeNameInfo>();
new (TI) TypeNameInfo(isTypename, II->getFETokenInfo<TypeNameInfo>());
II->setFETokenInfo(TI);
}
-
+
void DeleteEntry(TypeNameInfo *Entry) {
Entry->~TypeNameInfo();
Allocator.Deallocate(Entry);
@@ -107,7 +108,7 @@ static TypeNameInfoTable *getTable(void *TP) {
return static_cast<TypeNameInfoTable*>(TP);
}
-MinimalAction::MinimalAction(Preprocessor &pp)
+MinimalAction::MinimalAction(Preprocessor &pp)
: Idents(pp.getIdentifierTable()), PP(pp) {
TypeNameInfoTablePtr = new TypeNameInfoTable();
}
@@ -126,9 +127,9 @@ void MinimalAction::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
TNIT.AddEntry(true, &Idents.get("__int128_t"));
TNIT.AddEntry(true, &Idents.get("__uint128_t"));
}
-
+
if (PP.getLangOptions().ObjC1) {
- // Recognize the ObjC built-in type identifiers as types.
+ // Recognize the ObjC built-in type identifiers as types.
TNIT.AddEntry(true, &Idents.get("id"));
TNIT.AddEntry(true, &Idents.get("SEL"));
TNIT.AddEntry(true, &Idents.get("Class"));
@@ -143,7 +144,8 @@ void MinimalAction::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {
/// FIXME: Use the passed CXXScopeSpec for accurate C++ type checking.
Action::TypeTy *
MinimalAction::getTypeName(IdentifierInfo &II, SourceLocation Loc,
- Scope *S, const CXXScopeSpec *SS) {
+ Scope *S, const CXXScopeSpec *SS,
+ bool isClassName) {
if (TypeNameInfo *TI = II.getFETokenInfo<TypeNameInfo>())
if (TI->isTypeName)
return TI;
@@ -157,10 +159,14 @@ bool MinimalAction::isCurrentClassName(const IdentifierInfo &, Scope *,
return false;
}
-TemplateNameKind
-MinimalAction::isTemplateName(const IdentifierInfo &II, Scope *S,
- TemplateTy &TemplateDecl,
- const CXXScopeSpec *SS) {
+TemplateNameKind
+MinimalAction::isTemplateName(Scope *S,
+ const IdentifierInfo &II,
+ SourceLocation IdLoc,
+ const CXXScopeSpec *SS,
+ TypeTy *ObjectType,
+ bool EnteringScope,
+ TemplateTy &TemplateDecl) {
return TNK_Non_template;
}
@@ -170,10 +176,10 @@ MinimalAction::isTemplateName(const IdentifierInfo &II, Scope *S,
Action::DeclPtrTy
MinimalAction::ActOnDeclarator(Scope *S, Declarator &D) {
IdentifierInfo *II = D.getIdentifier();
-
+
// If there is no identifier associated with this declarator, bail out.
if (II == 0) return DeclPtrTy();
-
+
TypeNameInfo *weCurrentlyHaveTypeInfo = II->getFETokenInfo<TypeNameInfo>();
bool isTypeName =
D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef;
@@ -184,10 +190,10 @@ MinimalAction::ActOnDeclarator(Scope *S, Declarator &D) {
if (weCurrentlyHaveTypeInfo || isTypeName) {
// Allocate and add the 'TypeNameInfo' "decl".
getTable(TypeNameInfoTablePtr)->AddEntry(isTypeName, II);
-
+
// Remember that this needs to be removed when the scope is popped.
S->AddDecl(DeclPtrTy::make(II));
- }
+ }
return DeclPtrTy();
}
@@ -206,15 +212,15 @@ MinimalAction::ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
return DeclPtrTy();
}
-/// ActOnForwardClassDeclaration -
-/// Scope will always be top level file scope.
+/// ActOnForwardClassDeclaration -
+/// Scope will always be top level file scope.
Action::DeclPtrTy
MinimalAction::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
IdentifierInfo **IdentList, unsigned NumElts) {
for (unsigned i = 0; i != NumElts; ++i) {
// Allocate and add the 'TypeNameInfo' "decl".
getTable(TypeNameInfoTablePtr)->AddEntry(true, IdentList[i]);
-
+
// Remember that this needs to be removed when the scope is popped.
TUScope->AddDecl(DeclPtrTy::make(IdentList[i]));
}
@@ -225,17 +231,17 @@ MinimalAction::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
/// out-of-scope, they are removed from the IdentifierInfo::FETokenInfo field.
void MinimalAction::ActOnPopScope(SourceLocation Loc, Scope *S) {
TypeNameInfoTable &Table = *getTable(TypeNameInfoTablePtr);
-
+
for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
I != E; ++I) {
IdentifierInfo &II = *(*I).getAs<IdentifierInfo>();
TypeNameInfo *TI = II.getFETokenInfo<TypeNameInfo>();
assert(TI && "This decl didn't get pushed??");
-
+
if (TI) {
TypeNameInfo *Next = TI->Prev;
Table.DeleteEntry(TI);
-
+
II.setFETokenInfo(Next);
}
}
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index af6fab7cb188..c34653ee425c 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -21,17 +21,31 @@ using namespace clang;
/// Declarator is a well formed C++ inline method definition. Now lex its body
/// and store its tokens for parsing after the C++ class is complete.
Parser::DeclPtrTy
-Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) {
+Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D,
+ const ParsedTemplateInfo &TemplateInfo) {
assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
"This isn't a function declarator!");
assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) &&
"Current token not a '{', ':' or 'try'!");
- DeclPtrTy FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 0, 0);
+ Action::MultiTemplateParamsArg TemplateParams(Actions,
+ TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0,
+ TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0);
+ DeclPtrTy FnD;
+ if (D.getDeclSpec().isFriendSpecified())
+ // FIXME: Friend templates
+ FnD = Actions.ActOnFriendFunctionDecl(CurScope, D, true, move(TemplateParams));
+ else // FIXME: pass template information through
+ FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D,
+ move(TemplateParams), 0, 0);
+
+ HandleMemberFunctionDefaultArgs(D, FnD);
// Consume the tokens and store them for later parsing.
getCurrentClass().MethodDefs.push_back(LexedMethod(FnD));
+ getCurrentClass().MethodDefs.back().TemplateScope
+ = CurScope->isTemplateParamScope();
CachedTokens &Toks = getCurrentClass().MethodDefs.back().Toks;
tok::TokenKind kind = Tok.getKind();
@@ -40,7 +54,7 @@ Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) {
// Consume everything up to (and including) the left brace.
if (!ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks, tok::semi)) {
// We didn't find the left-brace we expected after the
- // constructor initializer.
+ // constructor initializer.
if (Tok.is(tok::semi)) {
// We found a semicolon; complain, consume the semicolon, and
// don't try to parse this method later.
@@ -52,7 +66,7 @@ Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) {
}
} else {
- // Begin by storing the '{' token.
+ // Begin by storing the '{' token.
Toks.push_back(Tok);
ConsumeBrace();
}
@@ -86,16 +100,18 @@ void Parser::ParseLexedMethodDeclarations(ParsingClass &Class) {
for (; !Class.MethodDecls.empty(); Class.MethodDecls.pop_front()) {
LateParsedMethodDeclaration &LM = Class.MethodDecls.front();
-
- // FIXME: For member function templates, we'll need to introduce a
- // scope for the template parameters.
+
+ // If this is a member template, introduce the template parameter scope.
+ ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
+ if (LM.TemplateScope)
+ Actions.ActOnReenterTemplateScope(CurScope, LM.Method);
// Start the delayed C++ method declaration
Actions.ActOnStartDelayedCXXMethodDeclaration(CurScope, LM.Method);
// Introduce the parameters into scope and parse their default
// arguments.
- ParseScope PrototypeScope(this,
+ ParseScope PrototypeScope(this,
Scope::FunctionPrototypeScope|Scope::DeclScope);
for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {
// Introduce the parameter into scope.
@@ -149,11 +165,16 @@ void Parser::ParseLexedMethodDefs(ParsingClass &Class) {
for (; !Class.MethodDefs.empty(); Class.MethodDefs.pop_front()) {
LexedMethod &LM = Class.MethodDefs.front();
+ // If this is a member template, introduce the template parameter scope.
+ ParseScope TemplateScope(this, Scope::TemplateParamScope, LM.TemplateScope);
+ if (LM.TemplateScope)
+ Actions.ActOnReenterTemplateScope(CurScope, LM.D);
+
assert(!LM.Toks.empty() && "Empty body!");
// Append the current token at the end of the new token stream so that it
// doesn't get lost.
LM.Toks.push_back(Tok);
- PP.EnterTokenStream(&LM.Toks.front(), LM.Toks.size(), true, false);
+ PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false);
// Consume the previously pushed token.
ConsumeAnyToken();
@@ -171,6 +192,9 @@ void Parser::ParseLexedMethodDefs(ParsingClass &Class) {
}
if (Tok.is(tok::colon))
ParseConstructorInitializer(LM.D);
+ else
+ Actions.ActOnDefaultCtorInitializers(LM.D);
+
// FIXME: What if ParseConstructorInitializer doesn't leave us with a '{'??
ParseFunctionStatementBody(LM.D);
}
@@ -181,7 +205,7 @@ void Parser::ParseLexedMethodDefs(ParsingClass &Class) {
/// ConsumeAndStoreUntil - Consume and store the token at the passed token
/// container until the token 'T' is reached (which gets
-/// consumed/stored too, if ConsumeFinalToken).
+/// consumed/stored too, if ConsumeFinalToken).
/// If EarlyAbortIf is specified, then we will stop early if we find that
/// token at the top level.
/// Returns true if token 'T1' or 'T2' was found.
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 4a3532c4103b..b56c33170cbf 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -69,10 +69,10 @@ Action::TypeResult Parser::ParseTypeName(SourceRange *Range) {
/// typespec
/// typequal
/// storageclass
-///
+///
/// FIXME: The GCC grammar/code for this construct implies we need two
-/// token lookahead. Comment from gcc: "If they start with an identifier
-/// which is followed by a comma or close parenthesis, then the arguments
+/// token lookahead. Comment from gcc: "If they start with an identifier
+/// which is followed by a comma or close parenthesis, then the arguments
/// start with that identifier; otherwise they are an expression list."
///
/// At the moment, I am not doing 2 token lookahead. I am also unaware of
@@ -82,9 +82,9 @@ Action::TypeResult Parser::ParseTypeName(SourceRange *Range) {
AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) {
assert(Tok.is(tok::kw___attribute) && "Not an attribute list!");
-
+
AttributeList *CurrAttr = 0;
-
+
while (Tok.is(tok::kw___attribute)) {
ConsumeToken();
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
@@ -99,8 +99,8 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) {
// Parse the attribute-list. e.g. __attribute__(( weak, alias("__f") ))
while (Tok.is(tok::identifier) || isDeclarationSpecifier() ||
Tok.is(tok::comma)) {
-
- if (Tok.is(tok::comma)) {
+
+ if (Tok.is(tok::comma)) {
// allows for empty/non-empty attributes. ((__vector_size__(16),,,,))
ConsumeToken();
continue;
@@ -108,26 +108,26 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) {
// we have an identifier or declaration specifier (const, int, etc.)
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
-
+
// check if we have a "paramterized" attribute
if (Tok.is(tok::l_paren)) {
ConsumeParen(); // ignore the left paren loc for now
-
+
if (Tok.is(tok::identifier)) {
IdentifierInfo *ParmName = Tok.getIdentifierInfo();
SourceLocation ParmLoc = ConsumeToken();
-
- if (Tok.is(tok::r_paren)) {
+
+ if (Tok.is(tok::r_paren)) {
// __attribute__(( mode(byte) ))
ConsumeParen(); // ignore the right paren loc for now
- CurrAttr = new AttributeList(AttrName, AttrNameLoc,
+ CurrAttr = new AttributeList(AttrName, AttrNameLoc,
ParmName, ParmLoc, 0, 0, CurrAttr);
} else if (Tok.is(tok::comma)) {
ConsumeToken();
// __attribute__(( format(printf, 1, 2) ))
ExprVector ArgExprs(Actions);
bool ArgExprsOk = true;
-
+
// now parse the non-empty comma separated list of expressions
while (1) {
OwningExprResult ArgExpr(ParseAssignmentExpression());
@@ -144,7 +144,7 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) {
}
if (ArgExprsOk && Tok.is(tok::r_paren)) {
ConsumeParen(); // ignore the right paren loc for now
- CurrAttr = new AttributeList(AttrName, AttrNameLoc, ParmName,
+ CurrAttr = new AttributeList(AttrName, AttrNameLoc, ParmName,
ParmLoc, ArgExprs.take(), ArgExprs.size(), CurrAttr);
}
}
@@ -154,11 +154,13 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) {
// parse a possibly empty comma separated list of expressions
// __attribute__(( nonnull() ))
ConsumeParen(); // ignore the right paren loc for now
- CurrAttr = new AttributeList(AttrName, AttrNameLoc,
+ CurrAttr = new AttributeList(AttrName, AttrNameLoc,
0, SourceLocation(), 0, 0, CurrAttr);
break;
case tok::kw_char:
case tok::kw_wchar_t:
+ case tok::kw_char16_t:
+ case tok::kw_char32_t:
case tok::kw_bool:
case tok::kw_short:
case tok::kw_int:
@@ -172,7 +174,7 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) {
// If it's a builtin type name, eat it and expect a rparen
// __attribute__(( vec_type_hint(char) ))
ConsumeToken();
- CurrAttr = new AttributeList(AttrName, AttrNameLoc,
+ CurrAttr = new AttributeList(AttrName, AttrNameLoc,
0, SourceLocation(), 0, 0, CurrAttr);
if (Tok.is(tok::r_paren))
ConsumeParen();
@@ -181,7 +183,7 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) {
// __attribute__(( aligned(16) ))
ExprVector ArgExprs(Actions);
bool ArgExprsOk = true;
-
+
// now parse the list of expressions
while (1) {
OwningExprResult ArgExpr(ParseAssignmentExpression());
@@ -207,7 +209,7 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) {
}
}
} else {
- CurrAttr = new AttributeList(AttrName, AttrNameLoc,
+ CurrAttr = new AttributeList(AttrName, AttrNameLoc,
0, SourceLocation(), 0, 0, CurrAttr);
}
}
@@ -320,7 +322,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
default:
return ParseSimpleDeclaration(Context, DeclEnd);
}
-
+
// This routine returns a DeclGroup, if the thing we parsed only contains a
// single decl, convert it now.
return Actions.ConvertDeclToDeclGroup(SingleDecl);
@@ -339,7 +341,7 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
// Parse the common declaration-specifiers piece.
DeclSpec DS;
ParseDeclarationSpecifiers(DS);
-
+
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
// declaration-specifiers init-declarator-list[opt] ';'
if (Tok.is(tok::semi)) {
@@ -347,25 +349,25 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
-
+
Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context);
ParseDeclarator(DeclaratorInfo);
-
+
DeclGroupPtrTy DG =
ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
DeclEnd = Tok.getLocation();
-
+
// If the client wants to check what comes after the declaration, just return
// immediately without checking anything!
if (!RequireSemi) return DG;
-
+
if (Tok.is(tok::semi)) {
ConsumeToken();
return DG;
}
-
- Diag(Tok, diag::err_expected_semi_declation);
+
+ Diag(Tok, diag::err_expected_semi_declaration);
// Skip to end of block or statement
SkipUntil(tok::r_brace, true, true);
if (Tok.is(tok::semi))
@@ -404,27 +406,50 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D,
SkipUntil(tok::semi, true, true);
return DeclPtrTy();
}
-
+
D.setAsmLabel(AsmLabel.release());
D.SetRangeEnd(Loc);
}
-
+
// If attributes are present, parse them.
if (Tok.is(tok::kw___attribute)) {
SourceLocation Loc;
AttributeList *AttrList = ParseAttributes(&Loc);
D.AddAttributes(AttrList, Loc);
}
-
+
// Inform the current actions module that we just parsed this declarator.
- DeclPtrTy ThisDecl = TemplateInfo.TemplateParams?
- Actions.ActOnTemplateDeclarator(CurScope,
+ DeclPtrTy ThisDecl;
+ switch (TemplateInfo.Kind) {
+ case ParsedTemplateInfo::NonTemplate:
+ ThisDecl = Actions.ActOnDeclarator(CurScope, D);
+ break;
+
+ case ParsedTemplateInfo::Template:
+ case ParsedTemplateInfo::ExplicitSpecialization:
+ ThisDecl = Actions.ActOnTemplateDeclarator(CurScope,
Action::MultiTemplateParamsArg(Actions,
TemplateInfo.TemplateParams->data(),
TemplateInfo.TemplateParams->size()),
- D)
- : Actions.ActOnDeclarator(CurScope, D);
-
+ D);
+ break;
+
+ case ParsedTemplateInfo::ExplicitInstantiation: {
+ Action::DeclResult ThisRes
+ = Actions.ActOnExplicitInstantiation(CurScope,
+ TemplateInfo.ExternLoc,
+ TemplateInfo.TemplateLoc,
+ D);
+ if (ThisRes.isInvalid()) {
+ SkipUntil(tok::semi, true, true);
+ return DeclPtrTy();
+ }
+
+ ThisDecl = ThisRes.get();
+ break;
+ }
+ }
+
// Parse declarator '=' initializer.
if (Tok.is(tok::equal)) {
ConsumeToken();
@@ -444,7 +469,7 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D,
SkipUntil(tok::semi, true, true);
return DeclPtrTy();
}
- Actions.AddInitializerToDecl(ThisDecl, Actions.FullExpr(Init));
+ Actions.AddInitializerToDecl(ThisDecl, move(Init));
}
} else if (Tok.is(tok::l_paren)) {
// Parse C++ direct initializer: '(' expression-list ')'
@@ -465,7 +490,9 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D,
CommaLocs.data(), RParenLoc);
}
} else {
- Actions.ActOnUninitializedDecl(ThisDecl);
+ bool TypeContainsUndeducedAuto =
+ D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
+ Actions.ActOnUninitializedDecl(ThisDecl, TypeContainsUndeducedAuto);
}
return ThisDecl;
@@ -488,25 +515,25 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
// Declarators may be grouped together ("int X, *Y, Z();"). Remember the decls
// that we parse together here.
llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
-
+
// At this point, we know that it is not a function definition. Parse the
// rest of the init-declarator-list.
while (1) {
DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(D);
if (ThisDecl.get())
DeclsInGroup.push_back(ThisDecl);
-
+
// If we don't have a comma, it is either the end of the list (a ';') or an
// error, bail out.
if (Tok.isNot(tok::comma))
break;
-
+
// Consume the comma.
ConsumeToken();
-
+
// Parse the next declarator.
D.clear();
-
+
// Accept attributes in an init-declarator. In the first declarator in a
// declaration, these would be part of the declspec. In subsequent
// declarators, they become part of the declarator itself, so that they
@@ -519,10 +546,10 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
AttributeList *AttrList = ParseAttributes(&Loc);
D.AddAttributes(AttrList, Loc);
}
-
+
ParseDeclarator(D);
}
-
+
return Actions.FinalizeDeclaratorGroup(CurScope, D.getDeclSpec(),
DeclsInGroup.data(),
DeclsInGroup.size());
@@ -538,13 +565,13 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS) {
/// specifier-qualifier-list is a subset of declaration-specifiers. Just
/// parse declaration-specifiers and complain about extra stuff.
ParseDeclarationSpecifiers(DS);
-
+
// Validate declspec for type-name.
unsigned Specs = DS.getParsedSpecifiers();
if (Specs == DeclSpec::PQ_None && !DS.getNumProtocolQualifiers() &&
!DS.getAttributes())
Diag(Tok, diag::err_typename_requires_specqual);
-
+
// Issue diagnostic and remove storage class if present.
if (Specs & DeclSpec::PQ_StorageClassSpecifier) {
if (DS.getStorageClassSpecLoc().isValid())
@@ -553,7 +580,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS) {
Diag(DS.getThreadSpecLoc(), diag::err_typename_invalid_storageclass);
DS.ClearStorageClassSpecs();
}
-
+
// Issue diagnostic and remove function specfier if present.
if (Specs & DeclSpec::PQ_FunctionSpecifier) {
if (DS.isInlineSpecified())
@@ -604,7 +631,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
const ParsedTemplateInfo &TemplateInfo,
AccessSpecifier AS) {
assert(Tok.is(tok::identifier) && "should have identifier");
-
+
SourceLocation Loc = Tok.getLocation();
// If we see an identifier that is not a type name, we normally would
// parse it as the identifer being declared. However, when a typename
@@ -619,7 +646,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
// next token is obviously invalid for a type. Parse these as a case
// with an invalid type specifier.
assert(!DS.hasTypeSpecifier() && "Type specifier checked above");
-
+
// Since we know that this either implicit int (which is rare) or an
// error, we'd do lookahead to try to do better recovery.
if (isValidAfterIdentifierInDeclarator(NextToken())) {
@@ -628,7 +655,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
// identifier in the declarator.
return false;
}
-
+
// Otherwise, if we don't consume this token, we are going to emit an
// error anyway. Try to recover from various common problems. Check
// to see if this was a reference to a tag name without a tag specified.
@@ -638,7 +665,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
if (SS == 0) {
const char *TagName = 0;
tok::TokenKind TagKind = tok::unknown;
-
+
switch (Actions.isTagName(*Tok.getIdentifierInfo(), CurScope)) {
default: break;
case DeclSpec::TST_enum: TagName="enum" ;TagKind=tok::kw_enum ;break;
@@ -646,12 +673,12 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
case DeclSpec::TST_struct:TagName="struct";TagKind=tok::kw_struct;break;
case DeclSpec::TST_class: TagName="class" ;TagKind=tok::kw_class ;break;
}
-
+
if (TagName) {
Diag(Loc, diag::err_use_of_tag_name_without_tag)
<< Tok.getIdentifierInfo() << TagName
<< CodeModificationHint::CreateInsertion(Tok.getLocation(),TagName);
-
+
// Parse this as a tag as if the missing tag were present.
if (TagKind == tok::kw_enum)
ParseEnumSpecifier(Loc, DS, AS);
@@ -660,19 +687,43 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
return true;
}
}
-
- // Since this is almost certainly an invalid type name, emit a
- // diagnostic that says it, eat the token, and mark the declspec as
- // invalid.
- SourceRange R;
- if (SS) R = SS->getRange();
-
- Diag(Loc, diag::err_unknown_typename) << Tok.getIdentifierInfo() << R;
+
+ // This is almost certainly an invalid type name. Let the action emit a
+ // diagnostic and attempt to recover.
+ Action::TypeTy *T = 0;
+ if (Actions.DiagnoseUnknownTypeName(*Tok.getIdentifierInfo(), Loc,
+ CurScope, SS, T)) {
+ // The action emitted a diagnostic, so we don't have to.
+ if (T) {
+ // The action has suggested that the type T could be used. Set that as
+ // the type in the declaration specifiers, consume the would-be type
+ // name token, and we're done.
+ const char *PrevSpec;
+ unsigned DiagID;
+ DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T,
+ false);
+ DS.SetRangeEnd(Tok.getLocation());
+ ConsumeToken();
+
+ // There may be other declaration specifiers after this.
+ return true;
+ }
+
+ // Fall through; the action had no suggestion for us.
+ } else {
+ // The action did not emit a diagnostic, so emit one now.
+ SourceRange R;
+ if (SS) R = SS->getRange();
+ Diag(Loc, diag::err_unknown_typename) << Tok.getIdentifierInfo() << R;
+ }
+
+ // Mark this as an error.
const char *PrevSpec;
- DS.SetTypeSpecType(DeclSpec::TST_error, Loc, PrevSpec);
+ unsigned DiagID;
+ DS.SetTypeSpecType(DeclSpec::TST_error, Loc, PrevSpec, DiagID);
DS.SetRangeEnd(Tok.getLocation());
ConsumeToken();
-
+
// TODO: Could inject an invalid typedef decl in an enclosing scope to
// avoid rippling error messages on subsequent uses of the same type,
// could be useful if #include was forgotten.
@@ -703,24 +754,32 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
///
void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
const ParsedTemplateInfo &TemplateInfo,
- AccessSpecifier AS) {
+ AccessSpecifier AS,
+ DeclSpecContext DSContext) {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteOrdinaryName(CurScope);
+ ConsumeToken();
+ }
+
DS.SetRangeStart(Tok.getLocation());
while (1) {
- int isInvalid = false;
+ bool isInvalid = false;
const char *PrevSpec = 0;
+ unsigned DiagID = 0;
+
SourceLocation Loc = Tok.getLocation();
switch (Tok.getKind()) {
- default:
+ default:
DoneWithDeclSpec:
// If this is not a declaration specifier token, we're done reading decl
// specifiers. First verify that DeclSpec's are consistent.
DS.Finish(Diags, PP);
return;
-
+
case tok::coloncolon: // ::foo::bar
// Annotate C++ scope specifiers. If we get one, loop.
- if (TryAnnotateCXXScopeToken())
+ if (TryAnnotateCXXScopeToken(true))
continue;
goto DoneWithDeclSpec;
@@ -730,18 +789,31 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// We are looking for a qualified typename.
Token Next = NextToken();
- if (Next.is(tok::annot_template_id) &&
+ if (Next.is(tok::annot_template_id) &&
static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue())
->Kind == TNK_Type_template) {
// We have a qualified template-id, e.g., N::A<int>
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS);
- assert(Tok.is(tok::annot_template_id) &&
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true);
+ assert(Tok.is(tok::annot_template_id) &&
"ParseOptionalCXXScopeSpecifier not working");
AnnotateTemplateIdTokenAsType(&SS);
continue;
}
+ if (Next.is(tok::annot_typename)) {
+ // FIXME: is this scope-specifier getting dropped?
+ ConsumeToken(); // the scope-specifier
+ if (Tok.getAnnotationValue())
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc,
+ PrevSpec, DiagID,
+ Tok.getAnnotationValue());
+ else
+ DS.SetTypeSpecError();
+ DS.SetRangeEnd(Tok.getAnnotationEndLoc());
+ ConsumeToken(); // The typename
+ }
+
if (Next.isNot(tok::identifier))
goto DoneWithDeclSpec;
@@ -763,66 +835,69 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// If the referenced identifier is not a type, then this declspec is
// erroneous: We already checked about that it has no type specifier, and
// C++ doesn't have implicit int. Diagnose it as a typo w.r.t. to the
- // typename.
+ // typename.
if (TypeRep == 0) {
ConsumeToken(); // Eat the scope spec so the identifier is current.
if (ParseImplicitInt(DS, &SS, TemplateInfo, AS)) continue;
goto DoneWithDeclSpec;
}
-
+
ConsumeToken(); // The C++ scope.
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
- TypeRep);
+ DiagID, TypeRep);
if (isInvalid)
break;
-
+
DS.SetRangeEnd(Tok.getLocation());
ConsumeToken(); // The typename.
continue;
}
-
+
case tok::annot_typename: {
if (Tok.getAnnotationValue())
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
- Tok.getAnnotationValue());
+ DiagID, Tok.getAnnotationValue());
else
DS.SetTypeSpecError();
DS.SetRangeEnd(Tok.getAnnotationEndLoc());
ConsumeToken(); // The typename
-
+
// Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
// is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
// Objective-C interface. If we don't have Objective-C or a '<', this is
// just a normal reference to a typedef name.
if (!Tok.is(tok::less) || !getLang().ObjC1)
continue;
-
- SourceLocation EndProtoLoc;
+
+ SourceLocation LAngleLoc, EndProtoLoc;
llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl;
- ParseObjCProtocolReferences(ProtocolDecl, false, EndProtoLoc);
- DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size());
-
+ llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
+ ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
+ LAngleLoc, EndProtoLoc);
+ DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
+ ProtocolLocs.data(), LAngleLoc);
+
DS.SetRangeEnd(EndProtoLoc);
continue;
}
-
+
// typedef-name
case tok::identifier: {
// In C++, check to see if this is a scope specifier like foo::bar::, if
// so handle it as such. This is important for ctor parsing.
- if (getLang().CPlusPlus && TryAnnotateCXXScopeToken())
+ if (getLang().CPlusPlus && TryAnnotateCXXScopeToken(true))
continue;
-
+
// This identifier can only be a typedef name if we haven't already seen
// a type-specifier. Without this check we misparse:
// typedef int X; struct Y { short X; }; as 'short int'.
if (DS.hasTypeSpecifier())
goto DoneWithDeclSpec;
-
+
// It has to be available as a typedef too!
- TypeTy *TypeRep = Actions.getTypeName(*Tok.getIdentifierInfo(),
+ TypeTy *TypeRep = Actions.getTypeName(*Tok.getIdentifierInfo(),
Tok.getLocation(), CurScope);
// If this is not a typedef name, don't parse it as part of the declspec,
@@ -836,16 +911,19 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// being defined and the next token is a '(', then this is a
// constructor declaration. We're done with the decl-specifiers
// and will treat this token as an identifier.
- if (getLang().CPlusPlus && CurScope->isClassScope() &&
- Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope) &&
+ if (getLang().CPlusPlus &&
+ (CurScope->isClassScope() ||
+ (CurScope->isTemplateParamScope() &&
+ CurScope->getParent()->isClassScope())) &&
+ Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope) &&
NextToken().getKind() == tok::l_paren)
goto DoneWithDeclSpec;
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
- TypeRep);
+ DiagID, TypeRep);
if (isInvalid)
break;
-
+
DS.SetRangeEnd(Tok.getLocation());
ConsumeToken(); // The identifier
@@ -855,12 +933,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// just a normal reference to a typedef name.
if (!Tok.is(tok::less) || !getLang().ObjC1)
continue;
-
- SourceLocation EndProtoLoc;
+
+ SourceLocation LAngleLoc, EndProtoLoc;
llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl;
- ParseObjCProtocolReferences(ProtocolDecl, false, EndProtoLoc);
- DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size());
-
+ llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
+ ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
+ LAngleLoc, EndProtoLoc);
+ DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
+ ProtocolLocs.data(), LAngleLoc);
+
DS.SetRangeEnd(EndProtoLoc);
// Need to support trailing type qualifiers (e.g. "id<p> const").
@@ -870,7 +951,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// type-name
case tok::annot_template_id: {
- TemplateIdAnnotation *TemplateId
+ TemplateIdAnnotation *TemplateId
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
if (TemplateId->Kind != TNK_Type_template) {
// This template-id does not refer to a type name, so we're
@@ -893,7 +974,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
case tok::kw___declspec:
DS.AddAttributes(ParseMicrosoftDeclSpec());
continue;
-
+
// Microsoft single token adornments.
case tok::kw___forceinline:
// FIXME: Add handling here!
@@ -909,106 +990,144 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// storage-class-specifier
case tok::kw_typedef:
- isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec);
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw_extern:
if (DS.isThreadSpecified())
Diag(Tok, diag::ext_thread_before) << "extern";
- isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, Loc, PrevSpec);
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw___private_extern__:
isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_private_extern, Loc,
- PrevSpec);
+ PrevSpec, DiagID);
break;
case tok::kw_static:
if (DS.isThreadSpecified())
Diag(Tok, diag::ext_thread_before) << "static";
- isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, Loc, PrevSpec);
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw_auto:
if (getLang().CPlusPlus0x)
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec,
+ DiagID);
else
- isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec);
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw_register:
- isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, Loc, PrevSpec);
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw_mutable:
- isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_mutable, Loc, PrevSpec);
+ isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_mutable, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw___thread:
- isInvalid = DS.SetStorageClassSpecThread(Loc, PrevSpec)*2;
+ isInvalid = DS.SetStorageClassSpecThread(Loc, PrevSpec, DiagID);
break;
-
+
// function-specifier
case tok::kw_inline:
- isInvalid = DS.SetFunctionSpecInline(Loc, PrevSpec);
+ isInvalid = DS.SetFunctionSpecInline(Loc, PrevSpec, DiagID);
break;
case tok::kw_virtual:
- isInvalid = DS.SetFunctionSpecVirtual(Loc, PrevSpec);
+ isInvalid = DS.SetFunctionSpecVirtual(Loc, PrevSpec, DiagID);
break;
case tok::kw_explicit:
- isInvalid = DS.SetFunctionSpecExplicit(Loc, PrevSpec);
+ isInvalid = DS.SetFunctionSpecExplicit(Loc, PrevSpec, DiagID);
break;
// friend
case tok::kw_friend:
- isInvalid = DS.SetFriendSpec(Loc, PrevSpec);
+ if (DSContext == DSC_class)
+ isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID);
+ else {
+ PrevSpec = ""; // not actually used by the diagnostic
+ DiagID = diag::err_friend_invalid_in_context;
+ isInvalid = true;
+ }
break;
-
+
// type-specifier
case tok::kw_short:
- isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw_long:
if (DS.getTypeSpecWidth() != DeclSpec::TSW_long)
- isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec,
+ DiagID);
else
- isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw_signed:
- isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw_unsigned:
- isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw__Complex:
- isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw__Imaginary:
- isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw_void:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw_char:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw_int:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw_float:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw_double:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw_wchar_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw_char16_t:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec,
+ DiagID);
+ break;
+ case tok::kw_char32_t:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw_bool:
case tok::kw__Bool:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw__Decimal32:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw__Decimal64:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw__Decimal128:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec,
+ DiagID);
break;
// class-specifier:
@@ -1029,15 +1148,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// cv-qualifier:
case tok::kw_const:
- isInvalid = DS.SetTypeQual(DeclSpec::TQ_const, Loc, PrevSpec,getLang())*2;
+ isInvalid = DS.SetTypeQual(DeclSpec::TQ_const, Loc, PrevSpec, DiagID,
+ getLang());
break;
case tok::kw_volatile:
- isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec,
- getLang())*2;
+ isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID,
+ getLang());
break;
case tok::kw_restrict:
- isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec,
- getLang())*2;
+ isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,
+ getLang());
break;
// C++ typename-specifier:
@@ -1061,12 +1181,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// but we support it.
if (DS.hasTypeSpecifier() || !getLang().ObjC1)
goto DoneWithDeclSpec;
-
+
{
- SourceLocation EndProtoLoc;
+ SourceLocation LAngleLoc, EndProtoLoc;
llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl;
- ParseObjCProtocolReferences(ProtocolDecl, false, EndProtoLoc);
- DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size());
+ llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
+ ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
+ LAngleLoc, EndProtoLoc);
+ DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
+ ProtocolLocs.data(), LAngleLoc);
DS.SetRangeEnd(EndProtoLoc);
Diag(Loc, diag::warn_objc_protocol_qualifier_missing_id)
@@ -1077,12 +1200,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
continue;
}
}
- // If the specifier combination wasn't legal, issue a diagnostic.
+ // If the specifier wasn't legal, issue a diagnostic.
if (isInvalid) {
assert(PrevSpec && "Method did not return previous specifier!");
- // Pick between error or extwarn.
- unsigned DiagID = isInvalid == 1 ? diag::err_invalid_decl_spec_combination
- : diag::ext_duplicate_declspec;
+ assert(DiagID);
Diag(Tok, DiagID) << PrevSpec;
}
DS.SetRangeEnd(Tok.getLocation());
@@ -1133,8 +1254,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
/// [OBJC] class-name objc-protocol-refs[opt] [TODO]
/// [OBJC] typedef-name objc-protocol-refs[opt] [TODO]
/// [C++0x] 'decltype' ( expression )
-bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid,
+bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
const char *&PrevSpec,
+ unsigned &DiagID,
const ParsedTemplateInfo &TemplateInfo) {
SourceLocation Loc = Tok.getLocation();
@@ -1144,98 +1266,117 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid,
// Annotate typenames and C++ scope specifiers. If we get one, just
// recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
- return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, TemplateInfo);
+ return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
+ TemplateInfo);
// Otherwise, not a type specifier.
return false;
case tok::coloncolon: // ::foo::bar
if (NextToken().is(tok::kw_new) || // ::new
NextToken().is(tok::kw_delete)) // ::delete
return false;
-
+
// Annotate typenames and C++ scope specifiers. If we get one, just
// recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
- return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, TemplateInfo);
+ return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
+ TemplateInfo);
// Otherwise, not a type specifier.
return false;
-
+
// simple-type-specifier:
case tok::annot_typename: {
if (Tok.getAnnotationValue())
isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
- Tok.getAnnotationValue());
+ DiagID, Tok.getAnnotationValue());
else
DS.SetTypeSpecError();
DS.SetRangeEnd(Tok.getAnnotationEndLoc());
ConsumeToken(); // The typename
-
+
// Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
// is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
// Objective-C interface. If we don't have Objective-C or a '<', this is
// just a normal reference to a typedef name.
if (!Tok.is(tok::less) || !getLang().ObjC1)
return true;
-
- SourceLocation EndProtoLoc;
+
+ SourceLocation LAngleLoc, EndProtoLoc;
llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl;
- ParseObjCProtocolReferences(ProtocolDecl, false, EndProtoLoc);
- DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size());
-
+ llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
+ ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
+ LAngleLoc, EndProtoLoc);
+ DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
+ ProtocolLocs.data(), LAngleLoc);
+
DS.SetRangeEnd(EndProtoLoc);
return true;
}
case tok::kw_short:
- isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID);
break;
case tok::kw_long:
if (DS.getTypeSpecWidth() != DeclSpec::TSW_long)
- isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec,
+ DiagID);
else
- isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw_signed:
- isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID);
break;
case tok::kw_unsigned:
- isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw__Complex:
- isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw__Imaginary:
- isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw_void:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID);
break;
case tok::kw_char:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID);
break;
case tok::kw_int:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID);
break;
case tok::kw_float:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID);
break;
case tok::kw_double:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID);
break;
case tok::kw_wchar_t:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_char16_t:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_char32_t:
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID);
break;
case tok::kw_bool:
case tok::kw__Bool:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID);
break;
case tok::kw__Decimal32:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw__Decimal64:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec,
+ DiagID);
break;
case tok::kw__Decimal128:
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec,
+ DiagID);
break;
// class-specifier:
@@ -1257,15 +1398,15 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid,
// cv-qualifier:
case tok::kw_const:
isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec,
- getLang())*2;
+ DiagID, getLang());
break;
case tok::kw_volatile:
isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec,
- getLang())*2;
+ DiagID, getLang());
break;
case tok::kw_restrict:
isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec,
- getLang())*2;
+ DiagID, getLang());
break;
// GNU typeof support.
@@ -1277,13 +1418,13 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid,
case tok::kw_decltype:
ParseDecltypeSpecifier(DS);
return true;
-
+
// C++0x auto support.
case tok::kw_auto:
if (!getLang().CPlusPlus0x)
return false;
- isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec);
+ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec, DiagID);
break;
case tok::kw___ptr64:
case tok::kw___w64:
@@ -1302,8 +1443,6 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid,
if (isInvalid) {
assert(PrevSpec && "Method did not return previous specifier!");
// Pick between error or extwarn.
- unsigned DiagID = isInvalid == 1 ? diag::err_invalid_decl_spec_combination
- : diag::ext_duplicate_declspec;
Diag(Tok, DiagID) << PrevSpec;
}
DS.SetRangeEnd(Tok.getLocation());
@@ -1337,11 +1476,11 @@ ParseStructDeclaration(DeclSpec &DS,
ConsumeToken();
return ParseStructDeclaration(DS, Fields);
}
-
+
// Parse the common specifier-qualifiers-list piece.
SourceLocation DSStart = Tok.getLocation();
ParseSpecifierQualifierList(DS);
-
+
// If there are no declarators, this is a free-standing declaration
// specifier. Let the actions module cope with it.
if (Tok.is(tok::semi)) {
@@ -1353,12 +1492,12 @@ ParseStructDeclaration(DeclSpec &DS,
Fields.push_back(FieldDeclarator(DS));
while (1) {
FieldDeclarator &DeclaratorInfo = Fields.back();
-
+
/// struct-declarator: declarator
/// struct-declarator: declarator[opt] ':' constant-expression
if (Tok.isNot(tok::colon))
ParseDeclarator(DeclaratorInfo.D);
-
+
if (Tok.is(tok::colon)) {
ConsumeToken();
OwningExprResult Res(ParseConstantExpression());
@@ -1410,9 +1549,9 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
PrettyStackTraceActionsDecl CrashInfo(TagDecl, RecordLoc, Actions,
PP.getSourceManager(),
"parsing struct/union body");
-
+
SourceLocation LBraceLoc = ConsumeBrace();
-
+
ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope);
Actions.ActOnTagStartDefinition(CurScope, TagDecl);
@@ -1428,7 +1567,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
// While we still have something to read, read the declarations in the struct.
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
// Each iteration of this loop reads one struct-declaration.
-
+
// Check for extraneous top-level semicolon.
if (Tok.is(tok::semi)) {
Diag(Tok, diag::ext_extra_struct_semi)
@@ -1442,14 +1581,23 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
FieldDeclarators.clear();
if (!Tok.is(tok::at)) {
ParseStructDeclaration(DS, FieldDeclarators);
-
+
// Convert them all to fields.
for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) {
FieldDeclarator &FD = FieldDeclarators[i];
+ DeclPtrTy Field;
// Install the declarator into the current TagDecl.
- DeclPtrTy Field = Actions.ActOnField(CurScope, TagDecl,
- DS.getSourceRange().getBegin(),
- FD.D, FD.BitfieldSize);
+ if (FD.D.getExtension()) {
+ // Silences extension warnings
+ ExtensionRAIIObject O(Diags);
+ Field = Actions.ActOnField(CurScope, TagDecl,
+ DS.getSourceRange().getBegin(),
+ FD.D, FD.BitfieldSize);
+ } else {
+ Field = Actions.ActOnField(CurScope, TagDecl,
+ DS.getSourceRange().getBegin(),
+ FD.D, FD.BitfieldSize);
+ }
FieldDecls.push_back(Field);
}
} else { // Handle @defs
@@ -1467,12 +1615,12 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
continue;
}
llvm::SmallVector<DeclPtrTy, 16> Fields;
- Actions.ActOnDefs(CurScope, TagDecl, Tok.getLocation(),
+ Actions.ActOnDefs(CurScope, TagDecl, Tok.getLocation(),
Tok.getIdentifierInfo(), Fields);
FieldDecls.insert(FieldDecls.end(), Fields.begin(), Fields.end());
ConsumeToken();
ExpectAndConsume(tok::r_paren, diag::err_expected_rparen);
- }
+ }
if (Tok.is(tok::semi)) {
ConsumeToken();
@@ -1485,9 +1633,9 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
SkipUntil(tok::r_brace, true, true);
}
}
-
+
SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
-
+
AttributeList *AttrList = 0;
// If attributes exist after struct contents, parse them.
if (Tok.is(tok::kw___attribute))
@@ -1498,7 +1646,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
LBraceLoc, RBraceLoc,
AttrList);
StructScope.Exit();
- Actions.ActOnTagFinishDefinition(CurScope, TagDecl);
+ Actions.ActOnTagFinishDefinition(CurScope, TagDecl, RBraceLoc);
}
@@ -1517,14 +1665,19 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
AccessSpecifier AS) {
// Parse the tag portion of this.
-
+ if (Tok.is(tok::code_completion)) {
+ // Code completion for an enum name.
+ Actions.CodeCompleteTag(CurScope, DeclSpec::TST_enum);
+ ConsumeToken();
+ }
+
AttributeList *Attr = 0;
// If attributes exist after tag, parse them.
if (Tok.is(tok::kw___attribute))
Attr = ParseAttributes();
CXXScopeSpec SS;
- if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS)) {
+ if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS, 0, false)) {
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
if (Tok.isNot(tok::l_brace)) {
@@ -1535,16 +1688,16 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
}
}
}
-
+
// Must have either 'enum name' or 'enum {...}'.
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace)) {
Diag(Tok, diag::err_expected_ident_lbrace);
-
+
// Skip the rest of this declarator, up until the comma or semicolon.
SkipUntil(tok::comma, true);
return;
}
-
+
// If an identifier is present, consume and remember it.
IdentifierInfo *Name = 0;
SourceLocation NameLoc;
@@ -1552,7 +1705,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
Name = Tok.getIdentifierInfo();
NameLoc = ConsumeToken();
}
-
+
// There are three options here. If we have 'enum foo;', then this is a
// forward declaration. If we have 'enum foo {...' then this is a
// definition. Otherwise we have something like 'enum foo xyz', a reference.
@@ -1561,26 +1714,30 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
// enum foo {..}; void bar() { enum foo; } <- new foo in bar.
// enum foo {..}; void bar() { enum foo x; } <- use of old foo.
//
- Action::TagKind TK;
+ Action::TagUseKind TUK;
if (Tok.is(tok::l_brace))
- TK = Action::TK_Definition;
+ TUK = Action::TUK_Definition;
else if (Tok.is(tok::semi))
- TK = Action::TK_Declaration;
+ TUK = Action::TUK_Declaration;
else
- TK = Action::TK_Reference;
+ TUK = Action::TUK_Reference;
bool Owned = false;
- DeclPtrTy TagDecl = Actions.ActOnTag(CurScope, DeclSpec::TST_enum, TK,
+ bool IsDependent = false;
+ DeclPtrTy TagDecl = Actions.ActOnTag(CurScope, DeclSpec::TST_enum, TUK,
StartLoc, SS, Name, NameLoc, Attr, AS,
- Owned);
-
+ Action::MultiTemplateParamsArg(Actions),
+ Owned, IsDependent);
+ assert(!IsDependent && "didn't expect dependent enum");
+
if (Tok.is(tok::l_brace))
ParseEnumBody(StartLoc, TagDecl);
-
+
// TODO: semantic analysis on the declspec for enums.
const char *PrevSpec = 0;
- if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc, PrevSpec,
+ unsigned DiagID;
+ if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc, PrevSpec, DiagID,
TagDecl.getAs<void>(), Owned))
- Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
+ Diag(StartLoc, DiagID) << PrevSpec;
}
/// ParseEnumBody - Parse a {} enclosed enumerator-list.
@@ -1599,20 +1756,20 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, DeclPtrTy EnumDecl) {
Actions.ActOnTagStartDefinition(CurScope, EnumDecl);
SourceLocation LBraceLoc = ConsumeBrace();
-
+
// C does not allow an empty enumerator-list, C++ does [dcl.enum].
if (Tok.is(tok::r_brace) && !getLang().CPlusPlus)
Diag(Tok, diag::ext_empty_struct_union_enum) << "enum";
-
+
llvm::SmallVector<DeclPtrTy, 32> EnumConstantDecls;
DeclPtrTy LastEnumConstDecl;
-
+
// Parse the enumerator-list.
while (Tok.is(tok::identifier)) {
IdentifierInfo *Ident = Tok.getIdentifierInfo();
SourceLocation IdentLoc = ConsumeToken();
-
+
SourceLocation EqualLoc;
OwningExprResult AssignedVal(Actions);
if (Tok.is(tok::equal)) {
@@ -1621,7 +1778,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, DeclPtrTy EnumDecl) {
if (AssignedVal.isInvalid())
SkipUntil(tok::comma, tok::r_brace, true, true);
}
-
+
// Install the enumerator constant into EnumDecl.
DeclPtrTy EnumConstDecl = Actions.ActOnEnumConstant(CurScope, EnumDecl,
LastEnumConstDecl,
@@ -1630,31 +1787,32 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, DeclPtrTy EnumDecl) {
AssignedVal.release());
EnumConstantDecls.push_back(EnumConstDecl);
LastEnumConstDecl = EnumConstDecl;
-
+
if (Tok.isNot(tok::comma))
break;
SourceLocation CommaLoc = ConsumeToken();
-
- if (Tok.isNot(tok::identifier) &&
+
+ if (Tok.isNot(tok::identifier) &&
!(getLang().C99 || getLang().CPlusPlus0x))
Diag(CommaLoc, diag::ext_enumerator_list_comma)
<< getLang().CPlusPlus
<< CodeModificationHint::CreateRemoval((SourceRange(CommaLoc)));
}
-
+
// Eat the }.
SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
- Actions.ActOnEnumBody(StartLoc, LBraceLoc, RBraceLoc, EnumDecl,
- EnumConstantDecls.data(), EnumConstantDecls.size());
-
- Action::AttrTy *AttrList = 0;
+ AttributeList *Attr = 0;
// If attributes exist after the identifier list, parse them.
if (Tok.is(tok::kw___attribute))
- AttrList = ParseAttributes(); // FIXME: where do they do?
+ Attr = ParseAttributes();
+
+ Actions.ActOnEnumBody(StartLoc, LBraceLoc, RBraceLoc, EnumDecl,
+ EnumConstantDecls.data(), EnumConstantDecls.size(),
+ CurScope, Attr);
EnumScope.Exit();
- Actions.ActOnTagFinishDefinition(CurScope, EnumDecl);
+ Actions.ActOnTagFinishDefinition(CurScope, EnumDecl, RBraceLoc);
}
/// isTypeSpecifierQualifier - Return true if the current token could be the
@@ -1675,7 +1833,7 @@ bool Parser::isTypeQualifier() const {
bool Parser::isTypeSpecifierQualifier() {
switch (Tok.getKind()) {
default: return false;
-
+
case tok::identifier: // foo::bar
case tok::kw_typename: // typename T::type
// Annotate typenames and C++ scope specifiers. If we get one, just
@@ -1696,12 +1854,12 @@ bool Parser::isTypeSpecifierQualifier() {
return isTypeSpecifierQualifier();
// Otherwise, not a type specifier.
return false;
-
+
// GNU attributes support.
case tok::kw___attribute:
// GNU typeof support.
case tok::kw_typeof:
-
+
// type-specifiers
case tok::kw_short:
case tok::kw_long:
@@ -1712,6 +1870,8 @@ bool Parser::isTypeSpecifierQualifier() {
case tok::kw_void:
case tok::kw_char:
case tok::kw_wchar_t:
+ case tok::kw_char16_t:
+ case tok::kw_char32_t:
case tok::kw_int:
case tok::kw_float:
case tok::kw_double:
@@ -1720,14 +1880,14 @@ bool Parser::isTypeSpecifierQualifier() {
case tok::kw__Decimal32:
case tok::kw__Decimal64:
case tok::kw__Decimal128:
-
+
// struct-or-union-specifier (C99) or class-specifier (C++)
case tok::kw_class:
case tok::kw_struct:
case tok::kw_union:
// enum-specifier
case tok::kw_enum:
-
+
// type-qualifier
case tok::kw_const:
case tok::kw_volatile:
@@ -1736,11 +1896,11 @@ bool Parser::isTypeSpecifierQualifier() {
// typedef-name
case tok::annot_typename:
return true;
-
+
// GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.
case tok::less:
return getLang().ObjC1;
-
+
case tok::kw___cdecl:
case tok::kw___stdcall:
case tok::kw___fastcall:
@@ -1755,7 +1915,7 @@ bool Parser::isTypeSpecifierQualifier() {
bool Parser::isDeclarationSpecifier() {
switch (Tok.getKind()) {
default: return false;
-
+
case tok::identifier: // foo::bar
// Unfortunate hack to support "Class.factoryMethod" notation.
if (getLang().ObjC1 && NextToken().is(tok::period))
@@ -1773,14 +1933,14 @@ bool Parser::isDeclarationSpecifier() {
if (NextToken().is(tok::kw_new) || // ::new
NextToken().is(tok::kw_delete)) // ::delete
return false;
-
+
// Annotate typenames and C++ scope specifiers. If we get one, just
// recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
return isDeclarationSpecifier();
// Otherwise, not a declaration specifier.
return false;
-
+
// storage-class-specifier
case tok::kw_typedef:
case tok::kw_extern:
@@ -1789,7 +1949,7 @@ bool Parser::isDeclarationSpecifier() {
case tok::kw_auto:
case tok::kw_register:
case tok::kw___thread:
-
+
// type-specifiers
case tok::kw_short:
case tok::kw_long:
@@ -1800,6 +1960,9 @@ bool Parser::isDeclarationSpecifier() {
case tok::kw_void:
case tok::kw_char:
case tok::kw_wchar_t:
+ case tok::kw_char16_t:
+ case tok::kw_char32_t:
+
case tok::kw_int:
case tok::kw_float:
case tok::kw_double:
@@ -1808,14 +1971,14 @@ bool Parser::isDeclarationSpecifier() {
case tok::kw__Decimal32:
case tok::kw__Decimal64:
case tok::kw__Decimal128:
-
+
// struct-or-union-specifier (C99) or class-specifier (C++)
case tok::kw_class:
case tok::kw_struct:
case tok::kw_union:
// enum-specifier
case tok::kw_enum:
-
+
// type-qualifier
case tok::kw_const:
case tok::kw_volatile:
@@ -1831,15 +1994,15 @@ bool Parser::isDeclarationSpecifier() {
// GNU typeof support.
case tok::kw_typeof:
-
+
// GNU attributes.
case tok::kw___attribute:
return true;
-
+
// GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.
case tok::less:
return getLang().ObjC1;
-
+
case tok::kw___declspec:
case tok::kw___cdecl:
case tok::kw___stdcall:
@@ -1861,22 +2024,23 @@ bool Parser::isDeclarationSpecifier() {
///
void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool AttributesAllowed) {
while (1) {
- int isInvalid = false;
+ bool isInvalid = false;
const char *PrevSpec = 0;
+ unsigned DiagID = 0;
SourceLocation Loc = Tok.getLocation();
switch (Tok.getKind()) {
case tok::kw_const:
- isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec,
- getLang())*2;
+ isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec, DiagID,
+ getLang());
break;
case tok::kw_volatile:
- isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec,
- getLang())*2;
+ isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID,
+ getLang());
break;
case tok::kw_restrict:
- isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec,
- getLang())*2;
+ isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,
+ getLang());
break;
case tok::kw___w64:
case tok::kw___ptr64:
@@ -1905,9 +2069,6 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool AttributesAllowed) {
// If the specifier combination wasn't legal, issue a diagnostic.
if (isInvalid) {
assert(PrevSpec && "Method did not return previous specifier!");
- // Pick between error or extwarn.
- unsigned DiagID = isInvalid == 1 ? diag::err_invalid_decl_spec_combination
- : diag::ext_duplicate_declspec;
Diag(Tok, DiagID) << PrevSpec;
}
ConsumeToken();
@@ -1947,6 +2108,8 @@ void Parser::ParseDeclarator(Declarator &D) {
void Parser::ParseDeclaratorInternal(Declarator &D,
DirectDeclParseFunction DirectDeclParser) {
+ if (Diags.hasAllExtensionsSilenced())
+ D.setExtension();
// C++ member pointers start with a '::' or a nested-name.
// Member pointers get special handling, since there's no place for the
// scope spec in the generic path below.
@@ -1954,8 +2117,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
(Tok.is(tok::coloncolon) || Tok.is(tok::identifier) ||
Tok.is(tok::annot_cxxscope))) {
CXXScopeSpec SS;
- if (ParseOptionalCXXScopeSpecifier(SS)) {
- if(Tok.isNot(tok::star)) {
+ if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true)) {
+ if (Tok.isNot(tok::star)) {
// The scope spec really belongs to the direct-declarator.
D.getCXXScopeSpec() = SS;
if (DirectDeclParser)
@@ -2013,7 +2176,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
SourceLocation());
else
// Remember that we parsed a Block type, and remember the type-quals.
- D.AddTypeInfo(DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(),
+ D.AddTypeInfo(DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(),
Loc, DS.TakeAttributes()),
SourceLocation());
} else {
@@ -2095,13 +2258,13 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
///
/// id-expression: [C++ 5.1]
/// unqualified-id
-/// qualified-id [TODO]
+/// qualified-id
///
/// unqualified-id: [C++ 5.1]
-/// identifier
+/// identifier
/// operator-function-id
-/// conversion-function-id [TODO]
-/// '~' class-name
+/// conversion-function-id
+/// '~' class-name
/// template-id
///
void Parser::ParseDirectDeclarator(Declarator &D) {
@@ -2111,7 +2274,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
if (D.mayHaveIdentifier()) {
// ParseDeclaratorInternal might already have parsed the scope.
bool afterCXXScope = D.getCXXScopeSpec().isSet() ||
- ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec());
+ ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0,
+ true);
if (afterCXXScope) {
// Change the declaration context for name lookup, until this function
// is exited (and the declarator has been parsed).
@@ -2122,11 +2286,12 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
assert(Tok.getIdentifierInfo() && "Not an identifier?");
// If this identifier is the name of the current class, it's a
- // constructor name.
+ // constructor name.
if (!D.getDeclSpec().hasTypeSpecifier() &&
Actions.isCurrentClassName(*Tok.getIdentifierInfo(),CurScope)) {
+ CXXScopeSpec *SS = afterCXXScope? &D.getCXXScopeSpec() : 0;
D.setConstructor(Actions.getTypeName(*Tok.getIdentifierInfo(),
- Tok.getLocation(), CurScope),
+ Tok.getLocation(), CurScope, SS),
Tok.getLocation());
// This is a normal identifier.
} else
@@ -2134,18 +2299,10 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
ConsumeToken();
goto PastIdentifier;
} else if (Tok.is(tok::annot_template_id)) {
- TemplateIdAnnotation *TemplateId
+ TemplateIdAnnotation *TemplateId
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
- // FIXME: Could this template-id name a constructor?
-
- // FIXME: This is an egregious hack, where we silently ignore
- // the specialization (which should be a function template
- // specialization name) and use the name instead. This hack
- // will go away when we have support for function
- // specializations.
- D.SetIdentifier(TemplateId->Name, Tok.getLocation());
- TemplateId->Destroy();
+ D.setTemplateId(TemplateId);
ConsumeToken();
goto PastIdentifier;
} else if (Tok.is(tok::kw_operator)) {
@@ -2167,17 +2324,18 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
} else if (Tok.is(tok::tilde)) {
// This should be a C++ destructor.
SourceLocation TildeLoc = ConsumeToken();
- if (Tok.is(tok::identifier)) {
+ if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) {
// FIXME: Inaccurate.
SourceLocation NameLoc = Tok.getLocation();
SourceLocation EndLoc;
- TypeResult Type = ParseClassName(EndLoc);
+ CXXScopeSpec *SS = afterCXXScope? &D.getCXXScopeSpec() : 0;
+ TypeResult Type = ParseClassName(EndLoc, SS, true);
if (Type.isInvalid())
D.SetIdentifier(0, TildeLoc);
else
D.setDestructor(Type.get(), TildeLoc, NameLoc);
} else {
- Diag(Tok, diag::err_expected_class_name);
+ Diag(Tok, diag::err_destructor_class_name);
D.SetIdentifier(0, TildeLoc);
}
goto PastIdentifier;
@@ -2222,11 +2380,11 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
D.SetIdentifier(0, Tok.getLocation());
D.setInvalidType(true);
}
-
+
PastIdentifier:
assert(D.isPastIdentifier() &&
"Haven't past the location of the identifier yet?");
-
+
while (1) {
if (Tok.is(tok::l_paren)) {
// The paren may be part of a C++ direct initializer, eg. "int x(1);".
@@ -2250,7 +2408,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
/// ParseParenDeclarator - We parsed the declarator D up to a paren. This is
/// only called before the identifier, so these are most likely just grouping
-/// parens for precedence. If we find that these are actually function
+/// parens for precedence. If we find that these are actually function
/// parameter parens in an abstract-declarator, we call ParseFunctionDeclarator.
///
/// direct-declarator:
@@ -2264,7 +2422,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
void Parser::ParseParenDeclarator(Declarator &D) {
SourceLocation StartLoc = ConsumeParen();
assert(!D.isPastIdentifier() && "Should be called before passing identifier");
-
+
// Eat any attributes before we look at whether this is a grouping or function
// declarator paren. If this is a grouping paren, the attribute applies to
// the type being built up, for example:
@@ -2279,7 +2437,7 @@ void Parser::ParseParenDeclarator(Declarator &D) {
bool RequiresArg = false;
if (Tok.is(tok::kw___attribute)) {
AttrList = ParseAttributes();
-
+
// We require that the argument list (if this is a non-grouping paren) be
// present even if the attribute list was empty.
RequiresArg = true;
@@ -2290,13 +2448,13 @@ void Parser::ParseParenDeclarator(Declarator &D) {
Tok.is(tok::kw___ptr64)) {
AttrList = ParseMicrosoftTypeAttributes(AttrList);
}
-
+
// If we haven't past the identifier yet (or where the identifier would be
// stored, if this is an abstract declarator), then this is probably just
// grouping parens. However, if this could be an abstract-declarator, then
// this could also be the start of function arguments (consider 'void()').
bool isGrouping;
-
+
if (!D.mayOmitIdentifier()) {
// If this can't be an abstract-declarator, this *must* be a grouping
// paren, because we haven't seen the identifier yet.
@@ -2311,7 +2469,7 @@ void Parser::ParseParenDeclarator(Declarator &D) {
// Otherwise, this is a grouping paren, e.g. 'int (*X)' or 'int(X)'.
isGrouping = true;
}
-
+
// If this is a grouping paren, handle:
// direct-declarator: '(' declarator ')'
// direct-declarator: '(' attributes declarator ')'
@@ -2329,7 +2487,7 @@ void Parser::ParseParenDeclarator(Declarator &D) {
D.SetRangeEnd(Loc);
return;
}
-
+
// Okay, if this wasn't a grouping paren, it must be the start of a function
// argument list. Recognize that this declarator will never have an
// identifier (and remember where it would have been), then call into
@@ -2353,6 +2511,7 @@ void Parser::ParseParenDeclarator(Declarator &D) {
/// parameter-type-list: [C99 6.7.5]
/// parameter-list
/// parameter-list ',' '...'
+/// [C++] parameter-list '...'
///
/// parameter-list: [C99 6.7.5]
/// parameter-declaration
@@ -2375,7 +2534,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
bool RequiresArg) {
// lparen is already consumed!
assert(D.isPastIdentifier() && "Should not call before identifier!");
-
+
// This parameter list may be empty.
if (Tok.is(tok::r_paren)) {
if (RequiresArg) {
@@ -2383,7 +2542,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
delete AttrList;
}
- SourceLocation Loc = ConsumeParen(); // Eat the closing ')'.
+ SourceLocation RParenLoc = ConsumeParen(); // Eat the closing ')'.
+ SourceLocation EndLoc = RParenLoc;
// cv-qualifier-seq[opt].
DeclSpec DS;
@@ -2395,13 +2555,13 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
if (getLang().CPlusPlus) {
ParseTypeQualifierListOpt(DS, false /*no attributes*/);
if (!DS.getSourceRange().getEnd().isInvalid())
- Loc = DS.getSourceRange().getEnd();
+ EndLoc = DS.getSourceRange().getEnd();
// Parse exception-specification[opt].
if (Tok.is(tok::kw_throw)) {
hasExceptionSpec = true;
ThrowLoc = Tok.getLocation();
- ParseExceptionSpecification(Loc, Exceptions, ExceptionRanges,
+ ParseExceptionSpecification(EndLoc, Exceptions, ExceptionRanges,
hasAnyExceptionSpec);
assert(Exceptions.size() == ExceptionRanges.size() &&
"Produced different number of exception types and ranges.");
@@ -2420,8 +2580,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
Exceptions.data(),
ExceptionRanges.data(),
Exceptions.size(),
- LParenLoc, D),
- Loc);
+ LParenLoc, RParenLoc, D),
+ EndLoc);
return;
}
@@ -2440,9 +2600,9 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
return ParseFunctionDeclaratorIdentifierList(LParenLoc, D);
}
}
-
+
// Finally, a normal, non-empty parameter type list.
-
+
// Build up an array of information about the parsed arguments.
llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
@@ -2450,7 +2610,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
// function prototype scope, including parameter declarators.
ParseScope PrototypeScope(this,
Scope::FunctionPrototypeScope|Scope::DeclScope);
-
+
bool IsVariadic = false;
SourceLocation EllipsisLoc;
while (1) {
@@ -2459,9 +2619,9 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
EllipsisLoc = ConsumeToken(); // Consume the ellipsis.
break;
}
-
+
SourceLocation DSStart = Tok.getLocation();
-
+
// Parse the declaration-specifiers.
DeclSpec DS;
@@ -2471,7 +2631,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
AttrList = 0; // Only apply the attributes to the first parameter.
}
ParseDeclarationSpecifiers(DS);
-
+
// Parse the declarator. This is "PrototypeContext", because we must
// accept either 'declarator' or 'abstract-declarator' here.
Declarator ParmDecl(DS, Declarator::PrototypeContext);
@@ -2483,10 +2643,10 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
AttributeList *AttrList = ParseAttributes(&Loc);
ParmDecl.AddAttributes(AttrList, Loc);
}
-
+
// Remember this parsed parameter in ParamInfo.
IdentifierInfo *ParmII = ParmDecl.getIdentifier();
-
+
// DefArgToks is used when the parsing of default arguments needs
// to be delayed.
CachedTokens *DefArgToks = 0;
@@ -2500,7 +2660,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
} else {
// Otherwise, we have something. Add it and let semantic analysis try
// to grok it and add the result to the ParamInfo we are building.
-
+
// Inform the actions module about the parameter declarator, so it gets
// added to the current scope.
DeclPtrTy Param = Actions.ActOnParamDeclarator(CurScope, ParmDecl);
@@ -2521,18 +2681,18 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
// FIXME: Can we use a smart pointer for Toks?
DefArgToks = new CachedTokens;
- if (!ConsumeAndStoreUntil(tok::comma, tok::r_paren, *DefArgToks,
+ if (!ConsumeAndStoreUntil(tok::comma, tok::r_paren, *DefArgToks,
tok::semi, false)) {
delete DefArgToks;
DefArgToks = 0;
Actions.ActOnParamDefaultArgumentError(Param);
} else
- Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc,
+ Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc,
(*DefArgToks)[1].getLocation());
} else {
// Consume the '='.
ConsumeToken();
-
+
OwningExprResult DefArgResult(ParseAssignmentExpression());
if (DefArgResult.isInvalid()) {
Actions.ActOnParamDefaultArgumentError(Param);
@@ -2544,24 +2704,39 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
}
}
}
-
- ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
- ParmDecl.getIdentifierLoc(), Param,
+
+ ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
+ ParmDecl.getIdentifierLoc(), Param,
DefArgToks));
}
// If the next token is a comma, consume it and keep reading arguments.
- if (Tok.isNot(tok::comma)) break;
-
+ if (Tok.isNot(tok::comma)) {
+ if (Tok.is(tok::ellipsis)) {
+ IsVariadic = true;
+ EllipsisLoc = ConsumeToken(); // Consume the ellipsis.
+
+ if (!getLang().CPlusPlus) {
+ // We have ellipsis without a preceding ',', which is ill-formed
+ // in C. Complain and provide the fix.
+ Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis)
+ << CodeModificationHint::CreateInsertion(EllipsisLoc, ", ");
+ }
+ }
+
+ break;
+ }
+
// Consume the comma.
ConsumeToken();
}
-
+
// Leave prototype scope.
PrototypeScope.Exit();
-
+
// If we have the closing ')', eat it.
- SourceLocation Loc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ SourceLocation EndLoc = RParenLoc;
DeclSpec DS;
bool hasExceptionSpec = false;
@@ -2573,13 +2748,13 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
// Parse cv-qualifier-seq[opt].
ParseTypeQualifierListOpt(DS, false /*no attributes*/);
if (!DS.getSourceRange().getEnd().isInvalid())
- Loc = DS.getSourceRange().getEnd();
+ EndLoc = DS.getSourceRange().getEnd();
// Parse exception-specification[opt].
if (Tok.is(tok::kw_throw)) {
hasExceptionSpec = true;
ThrowLoc = Tok.getLocation();
- ParseExceptionSpecification(Loc, Exceptions, ExceptionRanges,
+ ParseExceptionSpecification(EndLoc, Exceptions, ExceptionRanges,
hasAnyExceptionSpec);
assert(Exceptions.size() == ExceptionRanges.size() &&
"Produced different number of exception types and ranges.");
@@ -2595,8 +2770,9 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
hasAnyExceptionSpec,
Exceptions.data(),
ExceptionRanges.data(),
- Exceptions.size(), LParenLoc, D),
- Loc);
+ Exceptions.size(),
+ LParenLoc, RParenLoc, D),
+ EndLoc);
}
/// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator
@@ -2612,7 +2788,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
// Build up an array of information about the parsed arguments.
llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar;
-
+
// If there was no identifier specified for the declarator, either we are in
// an abstract-declarator, or we are in a parameter declarator which was found
// to be abstract. In abstract-declarators, identifier lists are not valid:
@@ -2626,13 +2802,13 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
ParamInfo.push_back(DeclaratorChunk::ParamInfo(Tok.getIdentifierInfo(),
Tok.getLocation(),
DeclPtrTy()));
-
+
ConsumeToken(); // eat the first identifier.
-
+
while (Tok.is(tok::comma)) {
// Eat the comma.
ConsumeToken();
-
+
// If this isn't an identifier, report the error and skip until ')'.
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
@@ -2645,7 +2821,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
// Reject 'typedef int y; int test(x, y)', but continue parsing.
if (Actions.getTypeName(*ParmII, Tok.getLocation(), CurScope))
Diag(Tok, diag::err_unexpected_typedef_ident) << ParmII;
-
+
// Verify that the argument identifier has not already been mentioned.
if (!ParamsSoFar.insert(ParmII)) {
Diag(Tok, diag::err_param_redefinition) << ParmII;
@@ -2655,7 +2831,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
Tok.getLocation(),
DeclPtrTy()));
}
-
+
// Eat the identifier.
ConsumeToken();
}
@@ -2672,7 +2848,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
/*TypeQuals*/0,
/*exception*/false,
SourceLocation(), false, 0, 0, 0,
- LParenLoc, D),
+ LParenLoc, RLoc, D),
RLoc);
}
@@ -2683,14 +2859,15 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
/// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
void Parser::ParseBracketDeclarator(Declarator &D) {
SourceLocation StartLoc = ConsumeBracket();
-
+
// C array syntax has many features, but by-far the most common is [] and [4].
// This code does a fast path to handle some of the most obvious cases.
if (Tok.getKind() == tok::r_square) {
SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
// Remember that we parsed the empty array type.
OwningExprResult NumElements(Actions);
- D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0, StartLoc),
+ D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0,
+ StartLoc, EndLoc),
EndLoc);
return;
} else if (Tok.getKind() == tok::numeric_constant &&
@@ -2704,33 +2881,33 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
// If there was an error parsing the assignment-expression, recover.
if (ExprRes.isInvalid())
ExprRes.release(); // Deallocate expr, just use [].
-
+
// Remember that we parsed a array type, and remember its features.
- D.AddTypeInfo(DeclaratorChunk::getArray(0, false, 0,
- ExprRes.release(), StartLoc),
+ D.AddTypeInfo(DeclaratorChunk::getArray(0, false, 0, ExprRes.release(),
+ StartLoc, EndLoc),
EndLoc);
return;
}
-
+
// If valid, this location is the position where we read the 'static' keyword.
SourceLocation StaticLoc;
if (Tok.is(tok::kw_static))
StaticLoc = ConsumeToken();
-
+
// If there is a type-qualifier-list, read it now.
// Type qualifiers in an array subscript are a C99 feature.
DeclSpec DS;
ParseTypeQualifierListOpt(DS, false /*no attributes*/);
-
+
// If we haven't already read 'static', check to see if there is one after the
// type-qualifier-list.
if (!StaticLoc.isValid() && Tok.is(tok::kw_static))
StaticLoc = ConsumeToken();
-
+
// Handle "direct-declarator [ type-qual-list[opt] * ]".
bool isStar = false;
OwningExprResult NumElements(Actions);
-
+
// Handle the case where we have '[*]' as the array size. However, a leading
// star could be the start of an expression, for example 'X[*p + 4]'. Verify
// the the token after the star is a ']'. Since stars in arrays are
@@ -2748,7 +2925,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
// of assignment-expr. The only difference is that assignment-expr allows
// things like '=' and '*='. Sema rejects these in C89 mode because they
// are not i-c-e's, so we don't need to distinguish between the two here.
-
+
// Parse the constant-expression or assignment-expression now (depending
// on dialect).
if (getLang().CPlusPlus)
@@ -2756,7 +2933,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
else
NumElements = ParseAssignmentExpression();
}
-
+
// If there was an error parsing the assignment-expression, recover.
if (NumElements.isInvalid()) {
D.setInvalidType(true);
@@ -2770,7 +2947,8 @@ void Parser::ParseBracketDeclarator(Declarator &D) {
// Remember that we parsed a array type, and remember its features.
D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(),
StaticLoc.isValid(), isStar,
- NumElements.release(), StartLoc),
+ NumElements.release(),
+ StartLoc, EndLoc),
EndLoc);
}
@@ -2797,7 +2975,7 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
DS.SetRangeEnd(Tok.getLocation());
else
DS.SetRangeEnd(CastRange.getEnd());
-
+
if (isCastExpr) {
if (!CastTy) {
DS.SetTypeSpecError();
@@ -2805,10 +2983,11 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
}
const char *PrevSpec = 0;
+ unsigned DiagID;
// Check for duplicate type specifiers (e.g. "int typeof(int)").
if (DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, PrevSpec,
- CastTy))
- Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
+ DiagID, CastTy))
+ Diag(StartLoc, DiagID) << PrevSpec;
return;
}
@@ -2819,8 +2998,9 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
}
const char *PrevSpec = 0;
+ unsigned DiagID;
// Check for duplicate type specifiers (e.g. "int typeof(int)").
if (DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc, PrevSpec,
- Operand.release()))
- Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
+ DiagID, Operand.release()))
+ Diag(StartLoc, DiagID) << PrevSpec;
}
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 373d22fd9f4f..d381e3e97472 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -38,7 +38,7 @@ using namespace clang;
///
/// extension-namespace-definition:
/// 'namespace' original-namespace-name '{' namespace-body '}'
-///
+///
/// namespace-alias-definition: [C++ 7.3.2: namespace.alias]
/// 'namespace' identifier '=' qualified-namespace-specifier ';'
///
@@ -46,17 +46,22 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
SourceLocation &DeclEnd) {
assert(Tok.is(tok::kw_namespace) && "Not a namespace!");
SourceLocation NamespaceLoc = ConsumeToken(); // eat the 'namespace'.
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteNamespaceDecl(CurScope);
+ ConsumeToken();
+ }
SourceLocation IdentLoc;
IdentifierInfo *Ident = 0;
Token attrTok;
-
+
if (Tok.is(tok::identifier)) {
Ident = Tok.getIdentifierInfo();
IdentLoc = ConsumeToken(); // eat the identifier.
}
-
+
// Read label attributes, if present.
Action::AttrTy *AttrList = 0;
if (Tok.is(tok::kw___attribute)) {
@@ -65,20 +70,20 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
// FIXME: save these somewhere.
AttrList = ParseAttributes();
}
-
+
if (Tok.is(tok::equal)) {
if (AttrList)
Diag(attrTok, diag::err_unexpected_namespace_attributes_alias);
return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd);
}
-
+
if (Tok.isNot(tok::l_brace)) {
- Diag(Tok, Ident ? diag::err_expected_lbrace :
+ Diag(Tok, Ident ? diag::err_expected_lbrace :
diag::err_expected_ident_lbrace);
return DeclPtrTy();
}
-
+
SourceLocation LBrace = ConsumeBrace();
// Enter a scope for the namespace.
@@ -90,10 +95,10 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
PrettyStackTraceActionsDecl CrashInfo(NamespcDecl, NamespaceLoc, Actions,
PP.getSourceManager(),
"parsing namespace");
-
+
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof))
ParseExternalDeclaration();
-
+
// Leave the namespace scope.
NamespaceScope.Exit();
@@ -108,16 +113,21 @@ Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
/// alias definition.
///
Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
- SourceLocation AliasLoc,
+ SourceLocation AliasLoc,
IdentifierInfo *Alias,
SourceLocation &DeclEnd) {
assert(Tok.is(tok::equal) && "Not equal token");
-
+
ConsumeToken(); // eat the '='.
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteNamespaceAliasDecl(CurScope);
+ ConsumeToken();
+ }
CXXScopeSpec SS;
// Parse (optional) nested-name-specifier.
- ParseOptionalCXXScopeSpecifier(SS);
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
if (SS.isInvalid() || Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_namespace_name);
@@ -129,13 +139,13 @@ Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
// Parse identifier.
IdentifierInfo *Ident = Tok.getIdentifierInfo();
SourceLocation IdentLoc = ConsumeToken();
-
+
// Eat the ';'.
DeclEnd = Tok.getLocation();
ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name,
"", tok::semi);
-
- return Actions.ActOnNamespaceAliasDef(CurScope, NamespaceLoc, AliasLoc, Alias,
+
+ return Actions.ActOnNamespaceAliasDef(CurScope, NamespaceLoc, AliasLoc, Alias,
SS, IdentLoc, Ident);
}
@@ -157,18 +167,18 @@ Parser::DeclPtrTy Parser::ParseLinkage(unsigned Context) {
SourceLocation Loc = ConsumeStringToken();
ParseScope LinkageScope(this, Scope::DeclScope);
- DeclPtrTy LinkageSpec
- = Actions.ActOnStartLinkageSpecification(CurScope,
+ DeclPtrTy LinkageSpec
+ = Actions.ActOnStartLinkageSpecification(CurScope,
/*FIXME: */SourceLocation(),
Loc, LangBufPtr, StrSize,
- Tok.is(tok::l_brace)? Tok.getLocation()
+ Tok.is(tok::l_brace)? Tok.getLocation()
: SourceLocation());
if (Tok.isNot(tok::l_brace)) {
ParseDeclarationOrFunctionDefinition();
- return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec,
+ return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec,
SourceLocation());
- }
+ }
SourceLocation LBrace = ConsumeBrace();
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
@@ -188,6 +198,11 @@ Parser::DeclPtrTy Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
// Eat 'using'.
SourceLocation UsingLoc = ConsumeToken();
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteUsing(CurScope);
+ ConsumeToken();
+ }
+
if (Tok.is(tok::kw_namespace))
// Next token after 'using' is 'namespace' so it must be using-directive
return ParseUsingDirective(Context, UsingLoc, DeclEnd);
@@ -214,9 +229,14 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
// Eat 'namespace'.
SourceLocation NamespcLoc = ConsumeToken();
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteUsingDirective(CurScope);
+ ConsumeToken();
+ }
+
CXXScopeSpec SS;
// Parse (optional) nested-name-specifier.
- ParseOptionalCXXScopeSpecifier(SS);
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
AttributeList *AttrList = 0;
IdentifierInfo *NamespcName = 0;
@@ -230,15 +250,15 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
// FIXME: Are there cases, when we would like to call ActOnUsingDirective?
return DeclPtrTy();
}
-
+
// Parse identifier.
NamespcName = Tok.getIdentifierInfo();
IdentLoc = ConsumeToken();
-
+
// Parse (optional) attributes (most likely GNU strong-using extension).
if (Tok.is(tok::kw___attribute))
AttrList = ParseAttributes();
-
+
// Eat ';'.
DeclEnd = Tok.getLocation();
ExpectAndConsume(tok::semi,
@@ -259,7 +279,8 @@ Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
///
Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
SourceLocation UsingLoc,
- SourceLocation &DeclEnd) {
+ SourceLocation &DeclEnd,
+ AccessSpecifier AS) {
CXXScopeSpec SS;
bool IsTypeName;
@@ -272,7 +293,7 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
IsTypeName = false;
// Parse nested-name-specifier.
- ParseOptionalCXXScopeSpecifier(SS);
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
AttributeList *AttrList = 0;
@@ -282,15 +303,17 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
return DeclPtrTy();
}
if (Tok.is(tok::annot_template_id)) {
- Diag(Tok, diag::err_unexpected_template_spec_in_using);
+ // C++0x N2914 [namespace.udecl]p5:
+ // A using-declaration shall not name a template-id.
+ Diag(Tok, diag::err_using_decl_can_not_refer_to_template_spec);
SkipUntil(tok::semi);
return DeclPtrTy();
}
-
+
IdentifierInfo *TargetName = 0;
OverloadedOperatorKind Op = OO_None;
SourceLocation IdentLoc;
-
+
if (Tok.is(tok::kw_operator)) {
IdentLoc = Tok.getLocation();
@@ -312,17 +335,17 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
SkipUntil(tok::semi);
return DeclPtrTy();
}
-
+
// Parse (optional) attributes (most likely GNU strong-using extension).
if (Tok.is(tok::kw___attribute))
AttrList = ParseAttributes();
-
+
// Eat ';'.
DeclEnd = Tok.getLocation();
ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
AttrList ? "attributes list" : "namespace name", tok::semi);
- return Actions.ActOnUsingDeclaration(CurScope, UsingLoc, SS,
+ return Actions.ActOnUsingDeclaration(CurScope, AS, UsingLoc, SS,
IdentLoc, TargetName, Op,
AttrList, IsTypeName);
}
@@ -335,12 +358,12 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
Parser::DeclPtrTy Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
assert(Tok.is(tok::kw_static_assert) && "Not a static_assert declaration");
SourceLocation StaticAssertLoc = ConsumeToken();
-
+
if (Tok.isNot(tok::l_paren)) {
Diag(Tok, diag::err_expected_lparen);
return DeclPtrTy();
}
-
+
SourceLocation LParenLoc = ConsumeParen();
OwningExprResult AssertExpr(ParseConstantExpression());
@@ -348,7 +371,7 @@ Parser::DeclPtrTy Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
SkipUntil(tok::semi);
return DeclPtrTy();
}
-
+
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", tok::semi))
return DeclPtrTy();
@@ -357,17 +380,17 @@ Parser::DeclPtrTy Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
SkipUntil(tok::semi);
return DeclPtrTy();
}
-
+
OwningExprResult AssertMessage(ParseStringLiteralExpression());
- if (AssertMessage.isInvalid())
+ if (AssertMessage.isInvalid())
return DeclPtrTy();
MatchRHSPunctuation(tok::r_paren, LParenLoc);
-
+
DeclEnd = Tok.getLocation();
ExpectAndConsume(tok::semi, diag::err_expected_semi_after_static_assert);
- return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc, move(AssertExpr),
+ return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc, move(AssertExpr),
move(AssertMessage));
}
@@ -380,15 +403,15 @@ void Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
SourceLocation StartLoc = ConsumeToken();
SourceLocation LParenLoc = Tok.getLocation();
-
- if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
+
+ if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
"decltype")) {
SkipUntil(tok::r_paren);
return;
}
-
+
// Parse the expression
-
+
// C++0x [dcl.type.simple]p4:
// The operand of the decltype specifier is an unevaluated operand.
EnterExpressionEvaluationContext Unevaluated(Actions,
@@ -398,22 +421,23 @@ void Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
SkipUntil(tok::r_paren);
return;
}
-
+
// Match the ')'
SourceLocation RParenLoc;
if (Tok.is(tok::r_paren))
RParenLoc = ConsumeParen();
else
MatchRHSPunctuation(tok::r_paren, LParenLoc);
-
+
if (RParenLoc.isInvalid())
return;
const char *PrevSpec = 0;
+ unsigned DiagID;
// Check for duplicate type specifiers (e.g. "int decltype(a)").
- if (DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, PrevSpec,
- Result.release()))
- Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
+ if (DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, PrevSpec,
+ DiagID, Result.release()))
+ Diag(StartLoc, DiagID) << PrevSpec;
}
/// ParseClassName - Parse a C++ class-name, which names a class. Note
@@ -425,12 +449,13 @@ void Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
/// class-name: [C++ 9.1]
/// identifier
/// simple-template-id
-///
+///
Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
- const CXXScopeSpec *SS) {
+ const CXXScopeSpec *SS,
+ bool DestrExpected) {
// Check whether we have a template-id that names a type.
if (Tok.is(tok::annot_template_id)) {
- TemplateIdAnnotation *TemplateId
+ TemplateIdAnnotation *TemplateId
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
if (TemplateId->Kind == TNK_Type_template) {
AnnotateTemplateIdTokenAsType(SS);
@@ -454,10 +479,12 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
}
// We have an identifier; check whether it is actually a type.
- TypeTy *Type = Actions.getTypeName(*Tok.getIdentifierInfo(),
- Tok.getLocation(), CurScope, SS);
+ TypeTy *Type = Actions.getTypeName(*Tok.getIdentifierInfo(),
+ Tok.getLocation(), CurScope, SS,
+ true);
if (!Type) {
- Diag(Tok, diag::err_expected_class_name);
+ Diag(Tok, DestrExpected ? diag::err_destructor_class_name
+ : diag::err_expected_class_name);
return true;
}
@@ -480,9 +507,9 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
/// class-key nested-name-specifier[opt] simple-template-id
/// base-clause[opt]
/// [GNU] class-key attributes[opt] identifier[opt] base-clause[opt]
-/// [GNU] class-key attributes[opt] nested-name-specifier
+/// [GNU] class-key attributes[opt] nested-name-specifier
/// identifier base-clause[opt]
-/// [GNU] class-key attributes[opt] nested-name-specifier[opt]
+/// [GNU] class-key attributes[opt] nested-name-specifier[opt]
/// simple-template-id base-clause[opt]
/// class-key:
/// 'class'
@@ -490,9 +517,9 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
/// 'union'
///
/// elaborated-type-specifier: [C++ dcl.type.elab]
-/// class-key ::[opt] nested-name-specifier[opt] identifier
-/// class-key ::[opt] nested-name-specifier[opt] 'template'[opt]
-/// simple-template-id
+/// class-key ::[opt] nested-name-specifier[opt] identifier
+/// class-key ::[opt] nested-name-specifier[opt] 'template'[opt]
+/// simple-template-id
///
/// Note that the C++ class-specifier and elaborated-type-specifier,
/// together, subsume the C99 struct-or-union-specifier:
@@ -520,6 +547,12 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
TagType = DeclSpec::TST_union;
}
+ if (Tok.is(tok::code_completion)) {
+ // Code completion for a struct, class, or union name.
+ Actions.CodeCompleteTag(CurScope, TagType);
+ ConsumeToken();
+ }
+
AttributeList *Attr = 0;
// If attributes exist after tag, parse them.
if (Tok.is(tok::kw___attribute))
@@ -528,10 +561,31 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// If declspecs exist after tag, parse them.
if (Tok.is(tok::kw___declspec))
Attr = ParseMicrosoftDeclSpec(Attr);
-
+
+ if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_pod)) {
+ // GNU libstdc++ 4.2 uses __is_pod as the name of a struct template, but
+ // __is_pod is a keyword in GCC >= 4.3. Therefore, when we see the
+ // token sequence "struct __is_pod", make __is_pod into a normal
+ // identifier rather than a keyword, to allow libstdc++ 4.2 to work
+ // properly.
+ Tok.getIdentifierInfo()->setTokenID(tok::identifier);
+ Tok.setKind(tok::identifier);
+ }
+
+ if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_empty)) {
+ // GNU libstdc++ 4.2 uses __is_empty as the name of a struct template, but
+ // __is_empty is a keyword in GCC >= 4.3. Therefore, when we see the
+ // token sequence "struct __is_empty", make __is_empty into a normal
+ // identifier rather than a keyword, to allow libstdc++ 4.2 to work
+ // properly.
+ Tok.getIdentifierInfo()->setTokenID(tok::identifier);
+ Tok.setKind(tok::identifier);
+ }
+
// Parse the (optional) nested-name-specifier.
CXXScopeSpec SS;
- if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS))
+ if (getLang().CPlusPlus &&
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true))
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
Diag(Tok, diag::err_expected_ident);
@@ -556,7 +610,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template)
<< Name << static_cast<int>(TemplateId->Kind) << Range;
-
+
DS.SetTypeSpecError();
SkipUntil(tok::semi, false, true);
TemplateId->Destroy();
@@ -564,19 +618,33 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
}
}
- // There are three options here. If we have 'struct foo;', then
- // this is a forward declaration. If we have 'struct foo {...' or
+ // There are four options here. If we have 'struct foo;', then this
+ // is either a forward declaration or a friend declaration, which
+ // have to be treated differently. If we have 'struct foo {...' or
// 'struct foo :...' then this is a definition. Otherwise we have
// something like 'struct foo xyz', a reference.
- Action::TagKind TK;
- if (Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon)))
- TK = Action::TK_Definition;
- else if (Tok.is(tok::semi) && !DS.isFriendSpecified())
- TK = Action::TK_Declaration;
+ Action::TagUseKind TUK;
+ if (Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon))) {
+ if (DS.isFriendSpecified()) {
+ // C++ [class.friend]p2:
+ // A class shall not be defined in a friend declaration.
+ Diag(Tok.getLocation(), diag::err_friend_decl_defines_class)
+ << SourceRange(DS.getFriendSpecLoc());
+
+ // Skip everything up to the semicolon, so that this looks like a proper
+ // friend class (or template thereof) declaration.
+ SkipUntil(tok::semi, true, true);
+ TUK = Action::TUK_Friend;
+ } else {
+ // Okay, this is a class definition.
+ TUK = Action::TUK_Definition;
+ }
+ } else if (Tok.is(tok::semi))
+ TUK = DS.isFriendSpecified() ? Action::TUK_Friend : Action::TUK_Declaration;
else
- TK = Action::TK_Reference;
+ TUK = Action::TUK_Reference;
- if (!Name && !TemplateId && TK != Action::TK_Definition) {
+ if (!Name && !TemplateId && TUK != Action::TUK_Definition) {
// We have a declaration or reference to an anonymous class.
Diag(StartLoc, diag::err_anon_type_definition)
<< DeclSpec::getSpecifierName(TagType);
@@ -590,36 +658,49 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
}
// Create the tag portion of the class or class template.
- Action::DeclResult TagOrTempResult;
+ Action::DeclResult TagOrTempResult = true; // invalid
+ Action::TypeResult TypeResult = true; // invalid
TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
- // FIXME: When TK == TK_Reference and we have a template-id, we need
+ // FIXME: When TUK == TUK_Reference and we have a template-id, we need
// to turn that template-id into a type.
bool Owned = false;
- if (TemplateId && TK != Action::TK_Reference) {
+ if (TemplateId) {
// Explicit specialization, class template partial specialization,
// or explicit instantiation.
- ASTTemplateArgsPtr TemplateArgsPtr(Actions,
+ ASTTemplateArgsPtr TemplateArgsPtr(Actions,
TemplateId->getTemplateArgs(),
TemplateId->getTemplateArgIsType(),
TemplateId->NumArgs);
if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
- TK == Action::TK_Declaration) {
+ TUK == Action::TUK_Declaration) {
// This is an explicit instantiation of a class template.
TagOrTempResult
- = Actions.ActOnExplicitInstantiation(CurScope,
- TemplateInfo.TemplateLoc,
+ = Actions.ActOnExplicitInstantiation(CurScope,
+ TemplateInfo.ExternLoc,
+ TemplateInfo.TemplateLoc,
TagType,
- StartLoc,
+ StartLoc,
SS,
- TemplateTy::make(TemplateId->Template),
- TemplateId->TemplateNameLoc,
- TemplateId->LAngleLoc,
+ TemplateTy::make(TemplateId->Template),
+ TemplateId->TemplateNameLoc,
+ TemplateId->LAngleLoc,
TemplateArgsPtr,
TemplateId->getTemplateArgLocations(),
- TemplateId->RAngleLoc,
+ TemplateId->RAngleLoc,
Attr);
+ } else if (TUK == Action::TUK_Reference) {
+ TypeResult
+ = Actions.ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
+ TemplateId->TemplateNameLoc,
+ TemplateId->LAngleLoc,
+ TemplateArgsPtr,
+ TemplateId->getTemplateArgLocations(),
+ TemplateId->RAngleLoc);
+
+ TypeResult = Actions.ActOnTagTemplateIdType(TypeResult, TUK,
+ TagType, StartLoc);
} else {
// This is an explicit specialization or a class template
// partial specialization.
@@ -634,11 +715,11 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// but it actually has a definition. Most likely, this was
// meant to be an explicit specialization, but the user forgot
// the '<>' after 'template'.
- assert(TK == Action::TK_Definition && "Expected a definition here");
+ assert(TUK == Action::TUK_Definition && "Expected a definition here");
- SourceLocation LAngleLoc
+ SourceLocation LAngleLoc
= PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
- Diag(TemplateId->TemplateNameLoc,
+ Diag(TemplateId->TemplateNameLoc,
diag::err_explicit_instantiation_with_definition)
<< SourceRange(TemplateInfo.TemplateLoc)
<< CodeModificationHint::CreateInsertion(LAngleLoc, "<>");
@@ -647,60 +728,64 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// "template<>", so that we treat this construct as a class
// template specialization.
FakedParamLists.push_back(
- Actions.ActOnTemplateParameterList(0, SourceLocation(),
+ Actions.ActOnTemplateParameterList(0, SourceLocation(),
TemplateInfo.TemplateLoc,
- LAngleLoc,
- 0, 0,
+ LAngleLoc,
+ 0, 0,
LAngleLoc));
TemplateParams = &FakedParamLists;
}
// Build the class template specialization.
TagOrTempResult
- = Actions.ActOnClassTemplateSpecialization(CurScope, TagType, TK,
+ = Actions.ActOnClassTemplateSpecialization(CurScope, TagType, TUK,
StartLoc, SS,
- TemplateTy::make(TemplateId->Template),
- TemplateId->TemplateNameLoc,
- TemplateId->LAngleLoc,
+ TemplateTy::make(TemplateId->Template),
+ TemplateId->TemplateNameLoc,
+ TemplateId->LAngleLoc,
TemplateArgsPtr,
TemplateId->getTemplateArgLocations(),
- TemplateId->RAngleLoc,
+ TemplateId->RAngleLoc,
Attr,
- Action::MultiTemplateParamsArg(Actions,
+ Action::MultiTemplateParamsArg(Actions,
TemplateParams? &(*TemplateParams)[0] : 0,
TemplateParams? TemplateParams->size() : 0));
}
TemplateId->Destroy();
- } else if (TemplateParams && TK != Action::TK_Reference) {
- // Class template declaration or definition.
- TagOrTempResult = Actions.ActOnClassTemplate(CurScope, TagType, TK,
- StartLoc, SS, Name, NameLoc,
- Attr,
- Action::MultiTemplateParamsArg(Actions,
- &(*TemplateParams)[0],
- TemplateParams->size()),
- AS);
} else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
- TK == Action::TK_Declaration) {
+ TUK == Action::TUK_Declaration) {
// Explicit instantiation of a member of a class template
// specialization, e.g.,
//
// template struct Outer<int>::Inner;
//
TagOrTempResult
- = Actions.ActOnExplicitInstantiation(CurScope,
- TemplateInfo.TemplateLoc,
- TagType, StartLoc, SS, Name,
+ = Actions.ActOnExplicitInstantiation(CurScope,
+ TemplateInfo.ExternLoc,
+ TemplateInfo.TemplateLoc,
+ TagType, StartLoc, SS, Name,
NameLoc, Attr);
} else {
if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
- TK == Action::TK_Definition) {
+ TUK == Action::TUK_Definition) {
// FIXME: Diagnose this particular error.
}
+ bool IsDependent = false;
+
// Declaration or definition of a class type
- TagOrTempResult = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, SS,
- Name, NameLoc, Attr, AS, Owned);
+ TagOrTempResult = Actions.ActOnTag(CurScope, TagType, TUK, StartLoc, SS,
+ Name, NameLoc, Attr, AS,
+ Action::MultiTemplateParamsArg(Actions,
+ TemplateParams? &(*TemplateParams)[0] : 0,
+ TemplateParams? TemplateParams->size() : 0),
+ Owned, IsDependent);
+
+ // If ActOnTag said the type was dependent, try again with the
+ // less common call.
+ if (IsDependent)
+ TypeResult = Actions.ActOnDependentTag(CurScope, TagType, TUK,
+ SS, Name, StartLoc, NameLoc);
}
// Parse the optional base clause (C++ only).
@@ -713,28 +798,33 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
ParseCXXMemberSpecification(StartLoc, TagType, TagOrTempResult.get());
else
ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get());
- else if (TK == Action::TK_Definition) {
+ else if (TUK == Action::TUK_Definition) {
// FIXME: Complain that we have a base-specifier list but no
// definition.
Diag(Tok, diag::err_expected_lbrace);
}
- const char *PrevSpec = 0;
- if (TagOrTempResult.isInvalid()) {
+ void *Result;
+ if (!TypeResult.isInvalid()) {
+ TagType = DeclSpec::TST_typename;
+ Result = TypeResult.get();
+ Owned = false;
+ } else if (!TagOrTempResult.isInvalid()) {
+ Result = TagOrTempResult.get().getAs<void>();
+ } else {
DS.SetTypeSpecError();
return;
}
-
- if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec,
- TagOrTempResult.get().getAs<void>(), Owned))
- Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
-
- if (DS.isFriendSpecified())
- Actions.ActOnFriendDecl(CurScope, DS.getFriendSpecLoc(),
- TagOrTempResult.get());
+
+ const char *PrevSpec = 0;
+ unsigned DiagID;
+
+ if (DS.SetTypeSpecType(TagType, StartLoc, PrevSpec, DiagID,
+ Result, Owned))
+ Diag(StartLoc, DiagID) << PrevSpec;
}
-/// ParseBaseClause - Parse the base-clause of a C++ class [C++ class.derived].
+/// ParseBaseClause - Parse the base-clause of a C++ class [C++ class.derived].
///
/// base-clause : [C++ class.derived]
/// ':' base-specifier-list
@@ -763,7 +853,7 @@ void Parser::ParseBaseClause(DeclPtrTy ClassDecl) {
// If the next token is a comma, consume it and keep reading
// base-specifiers.
if (Tok.isNot(tok::comma)) break;
-
+
// Consume the comma.
ConsumeToken();
}
@@ -797,7 +887,7 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) {
AccessSpecifier Access = getAccessSpecifierIfPresent();
if (Access)
ConsumeToken();
-
+
// Parse the 'virtual' keyword (again!), in case it came after the
// access specifier.
if (Tok.is(tok::kw_virtual)) {
@@ -813,7 +903,7 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) {
// Parse optional '::' and optional nested-name-specifier.
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS);
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true);
// The location of the base class itself.
SourceLocation BaseLoc = Tok.getLocation();
@@ -823,10 +913,10 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) {
TypeResult BaseType = ParseClassName(EndLocation, &SS);
if (BaseType.isInvalid())
return true;
-
- // Find the complete source range for the base-specifier.
+
+ // Find the complete source range for the base-specifier.
SourceRange Range(StartLoc, EndLocation);
-
+
// Notify semantic analysis that we have parsed a complete
// base-specifier.
return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access,
@@ -840,8 +930,7 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) {
/// 'private'
/// 'protected'
/// 'public'
-AccessSpecifier Parser::getAccessSpecifierIfPresent() const
-{
+AccessSpecifier Parser::getAccessSpecifierIfPresent() const {
switch (Tok.getKind()) {
default: return AS_none;
case tok::kw_private: return AS_private;
@@ -850,6 +939,40 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const
}
}
+void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,
+ DeclPtrTy ThisDecl) {
+ // We just declared a member function. If this member function
+ // has any default arguments, we'll need to parse them later.
+ LateParsedMethodDeclaration *LateMethod = 0;
+ DeclaratorChunk::FunctionTypeInfo &FTI
+ = DeclaratorInfo.getTypeObject(0).Fun;
+ for (unsigned ParamIdx = 0; ParamIdx < FTI.NumArgs; ++ParamIdx) {
+ if (LateMethod || FTI.ArgInfo[ParamIdx].DefaultArgTokens) {
+ if (!LateMethod) {
+ // Push this method onto the stack of late-parsed method
+ // declarations.
+ getCurrentClass().MethodDecls.push_back(
+ LateParsedMethodDeclaration(ThisDecl));
+ LateMethod = &getCurrentClass().MethodDecls.back();
+ LateMethod->TemplateScope = CurScope->isTemplateParamScope();
+
+ // Add all of the parameters prior to this one (they don't
+ // have default arguments).
+ LateMethod->DefaultArgs.reserve(FTI.NumArgs);
+ for (unsigned I = 0; I < ParamIdx; ++I)
+ LateMethod->DefaultArgs.push_back(
+ LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param));
+ }
+
+ // Add this parameter to the list of parameters (it or may
+ // not have a default argument).
+ LateMethod->DefaultArgs.push_back(
+ LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param,
+ FTI.ArgInfo[ParamIdx].DefaultArgTokens));
+ }
+ }
+}
+
/// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration.
///
/// member-declaration:
@@ -876,17 +999,21 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const
/// constant-initializer:
/// '=' constant-expression
///
-void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) {
+void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
+ const ParsedTemplateInfo &TemplateInfo) {
// static_assert-declaration
if (Tok.is(tok::kw_static_assert)) {
+ // FIXME: Check for templates
SourceLocation DeclEnd;
ParseStaticAssertDeclaration(DeclEnd);
return;
}
-
+
if (Tok.is(tok::kw_template)) {
+ assert(!TemplateInfo.TemplateParams &&
+ "Nested template improperly parsed?");
SourceLocation DeclEnd;
- ParseDeclarationStartingWithTemplate(Declarator::MemberContext, DeclEnd,
+ ParseDeclarationStartingWithTemplate(Declarator::MemberContext, DeclEnd,
AS);
return;
}
@@ -896,10 +1023,12 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) {
// __extension__ silences extension warnings in the subexpression.
ExtensionRAIIObject O(Diags); // Use RAII to do this.
ConsumeToken();
- return ParseCXXClassMemberDeclaration(AS);
+ return ParseCXXClassMemberDeclaration(AS, TemplateInfo);
}
if (Tok.is(tok::kw_using)) {
+ // FIXME: Check for template aliases
+
// Eat 'using'.
SourceLocation UsingLoc = ConsumeToken();
@@ -910,7 +1039,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) {
else {
SourceLocation DeclEnd;
// Otherwise, it must be using-declaration.
- ParseUsingDeclaration(Declarator::MemberContext, UsingLoc, DeclEnd);
+ ParseUsingDeclaration(Declarator::MemberContext, UsingLoc, DeclEnd, AS);
}
return;
}
@@ -919,24 +1048,16 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) {
// decl-specifier-seq:
// Parse the common declaration-specifiers piece.
DeclSpec DS;
- ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS);
+ ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class);
+
+ Action::MultiTemplateParamsArg TemplateParams(Actions,
+ TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0,
+ TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0);
if (Tok.is(tok::semi)) {
ConsumeToken();
- // C++ 9.2p7: The member-declarator-list can be omitted only after a
- // class-specifier or an enum-specifier or in a friend declaration.
- // FIXME: Friend declarations.
- switch (DS.getTypeSpecType()) {
- case DeclSpec::TST_struct:
- case DeclSpec::TST_union:
- case DeclSpec::TST_class:
- case DeclSpec::TST_enum:
- Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
- return;
- default:
- Diag(DSStart, diag::err_no_declarators);
- return;
- }
+ Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+ return;
}
Declarator DeclaratorInfo(DS, Declarator::MemberContext);
@@ -974,7 +1095,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) {
return;
}
- ParseCXXInlineMethodDef(AS, DeclaratorInfo);
+ ParseCXXInlineMethodDef(AS, DeclaratorInfo, TemplateInfo);
return;
}
}
@@ -1001,7 +1122,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) {
if (BitfieldSize.isInvalid())
SkipUntil(tok::comma, true, true);
}
-
+
// pure-specifier:
// '= 0'
//
@@ -1034,62 +1155,44 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) {
// NOTE: If Sema is the Action module and declarator is an instance field,
// this call will *not* return the created decl; It will return null.
// See Sema::ActOnCXXMemberDeclarator for details.
- DeclPtrTy ThisDecl = Actions.ActOnCXXMemberDeclarator(CurScope, AS,
- DeclaratorInfo,
- BitfieldSize.release(),
- Init.release(),
- Deleted);
+
+ DeclPtrTy ThisDecl;
+ if (DS.isFriendSpecified()) {
+ // TODO: handle initializers, bitfields, 'delete'
+ ThisDecl = Actions.ActOnFriendFunctionDecl(CurScope, DeclaratorInfo,
+ /*IsDefinition*/ false,
+ move(TemplateParams));
+ } else {
+ ThisDecl = Actions.ActOnCXXMemberDeclarator(CurScope, AS,
+ DeclaratorInfo,
+ move(TemplateParams),
+ BitfieldSize.release(),
+ Init.release(),
+ Deleted);
+ }
if (ThisDecl)
DeclsInGroup.push_back(ThisDecl);
if (DeclaratorInfo.isFunctionDeclarator() &&
- DeclaratorInfo.getDeclSpec().getStorageClassSpec()
+ DeclaratorInfo.getDeclSpec().getStorageClassSpec()
!= DeclSpec::SCS_typedef) {
- // We just declared a member function. If this member function
- // has any default arguments, we'll need to parse them later.
- LateParsedMethodDeclaration *LateMethod = 0;
- DeclaratorChunk::FunctionTypeInfo &FTI
- = DeclaratorInfo.getTypeObject(0).Fun;
- for (unsigned ParamIdx = 0; ParamIdx < FTI.NumArgs; ++ParamIdx) {
- if (LateMethod || FTI.ArgInfo[ParamIdx].DefaultArgTokens) {
- if (!LateMethod) {
- // Push this method onto the stack of late-parsed method
- // declarations.
- getCurrentClass().MethodDecls.push_back(
- LateParsedMethodDeclaration(ThisDecl));
- LateMethod = &getCurrentClass().MethodDecls.back();
-
- // Add all of the parameters prior to this one (they don't
- // have default arguments).
- LateMethod->DefaultArgs.reserve(FTI.NumArgs);
- for (unsigned I = 0; I < ParamIdx; ++I)
- LateMethod->DefaultArgs.push_back(
- LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param));
- }
-
- // Add this parameter to the list of parameters (it or may
- // not have a default argument).
- LateMethod->DefaultArgs.push_back(
- LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param,
- FTI.ArgInfo[ParamIdx].DefaultArgTokens));
- }
- }
+ HandleMemberFunctionDefaultArgs(DeclaratorInfo, ThisDecl);
}
// If we don't have a comma, it is either the end of the list (a ';')
// or an error, bail out.
if (Tok.isNot(tok::comma))
break;
-
+
// Consume the comma.
ConsumeToken();
-
+
// Parse the next declarator.
DeclaratorInfo.clear();
BitfieldSize = 0;
Init = 0;
Deleted = false;
-
+
// Attributes are only allowed on the second declarator.
if (Tok.is(tok::kw___attribute)) {
SourceLocation Loc;
@@ -1131,11 +1234,11 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
PrettyStackTraceActionsDecl CrashInfo(TagDecl, RecordLoc, Actions,
PP.getSourceManager(),
"parsing struct/union/class body");
-
+
SourceLocation LBraceLoc = ConsumeBrace();
// Determine whether this is a top-level (non-nested) class.
- bool TopLevelClass = ClassStack.empty() ||
+ bool TopLevelClass = ClassStack.empty() ||
CurScope->isInCXXInlineMethodScope();
// Enter a scope for the class.
@@ -1163,7 +1266,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
// While we still have something to read, read the member-declarations.
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
// Each iteration of this loop reads one member-declaration.
-
+
// Check for extraneous top-level semicolon.
if (Tok.is(tok::semi)) {
Diag(Tok, diag::ext_extra_struct_semi);
@@ -1180,12 +1283,14 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
continue;
}
+ // FIXME: Make sure we don't have a template here.
+
// Parse all the comma separated declarators.
ParseCXXClassMemberDeclaration(CurAS);
}
-
+
SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
-
+
AttributeList *AttrList = 0;
// If attributes exist after class contents, parse them.
if (Tok.is(tok::kw___attribute))
@@ -1213,7 +1318,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
ParsingDef.Pop();
ClassScope.Exit();
- Actions.ActOnTagFinishDefinition(CurScope, TagDecl);
+ Actions.ActOnTagFinishDefinition(CurScope, TagDecl, RBraceLoc);
}
/// ParseConstructorInitializer - Parse a C++ constructor initializer,
@@ -1231,19 +1336,19 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
/// };
/// @endcode
///
-/// [C++] ctor-initializer:
-/// ':' mem-initializer-list
+/// [C++] ctor-initializer:
+/// ':' mem-initializer-list
///
-/// [C++] mem-initializer-list:
-/// mem-initializer
-/// mem-initializer , mem-initializer-list
+/// [C++] mem-initializer-list:
+/// mem-initializer
+/// mem-initializer , mem-initializer-list
void Parser::ParseConstructorInitializer(DeclPtrTy ConstructorDecl) {
assert(Tok.is(tok::colon) && "Constructor initializer always starts with ':'");
SourceLocation ColonLoc = ConsumeToken();
-
+
llvm::SmallVector<MemInitTy*, 4> MemInitializers;
-
+
do {
MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);
if (!MemInit.isInvalid())
@@ -1261,7 +1366,7 @@ void Parser::ParseConstructorInitializer(DeclPtrTy ConstructorDecl) {
}
} while (true);
- Actions.ActOnMemInitializers(ConstructorDecl, ColonLoc,
+ Actions.ActOnMemInitializers(ConstructorDecl, ColonLoc,
MemInitializers.data(), MemInitializers.size());
}
@@ -1272,14 +1377,14 @@ void Parser::ParseConstructorInitializer(DeclPtrTy ConstructorDecl) {
///
/// [C++] mem-initializer:
/// mem-initializer-id '(' expression-list[opt] ')'
-///
+///
/// [C++] mem-initializer-id:
/// '::'[opt] nested-name-specifier[opt] class-name
/// identifier
Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) {
// parse '::'[opt] nested-name-specifier[opt]
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS);
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
TypeTy *TemplateTypeTy = 0;
if (Tok.is(tok::annot_template_id)) {
TemplateIdAnnotation *TemplateId
@@ -1295,7 +1400,7 @@ Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) {
Diag(Tok, diag::err_expected_member_or_base_name);
return true;
}
-
+
// Get the identifier. This may be a member name or a class name,
// but we'll let the semantic analysis determine which it is.
IdentifierInfo *II = Tok.is(tok::identifier) ? Tok.getIdentifierInfo() : 0;
@@ -1331,7 +1436,7 @@ Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) {
/// exception-specification:
/// 'throw' '(' type-id-list [opt] ')'
/// [MS] 'throw' '(' '...' ')'
-///
+///
/// type-id-list:
/// type-id
/// type-id-list ',' type-id
@@ -1343,9 +1448,9 @@ bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc,
&Ranges,
bool &hasAnyExceptionSpec) {
assert(Tok.is(tok::kw_throw) && "expected throw");
-
+
SourceLocation ThrowLoc = ConsumeToken();
-
+
if (!Tok.is(tok::l_paren)) {
return Diag(Tok, diag::err_expected_lparen_after) << "throw";
}
@@ -1384,7 +1489,7 @@ bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc,
/// so push that class onto our stack of classes that is currently
/// being parsed.
void Parser::PushParsingClass(DeclPtrTy ClassDecl, bool TopLevelClass) {
- assert((TopLevelClass || !ClassStack.empty()) &&
+ assert((TopLevelClass || !ClassStack.empty()) &&
"Nested class without outer class");
ClassStack.push(new ParsingClass(ClassDecl, TopLevelClass));
}
@@ -1408,7 +1513,7 @@ void Parser::DeallocateParsedClasses(Parser::ParsingClass *Class) {
/// false otherwise.
void Parser::PopParsingClass() {
assert(!ClassStack.empty() && "Mismatched push/pop for class parsing");
-
+
ParsingClass *Victim = ClassStack.top();
ClassStack.pop();
if (Victim->TopLevelClass) {
@@ -1416,7 +1521,7 @@ void Parser::PopParsingClass() {
// recursively: we don't need to keep any of this information.
DeallocateParsedClasses(Victim);
return;
- }
+ }
assert(!ClassStack.empty() && "Missing top-level class?");
if (Victim->MethodDecls.empty() && Victim->MethodDefs.empty() &&
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index cd7618f66536..72e30e3b6079 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -55,7 +55,7 @@ namespace prec {
/// getBinOpPrecedence - Return the precedence of the specified binary operator
/// token. This returns:
///
-static prec::Level getBinOpPrecedence(tok::TokenKind Kind,
+static prec::Level getBinOpPrecedence(tok::TokenKind Kind,
bool GreaterThanIsOperator,
bool CPlusPlus0x) {
switch (Kind) {
@@ -67,7 +67,7 @@ static prec::Level getBinOpPrecedence(tok::TokenKind Kind,
if (GreaterThanIsOperator)
return prec::Relational;
return prec::Unknown;
-
+
case tok::greatergreater:
// C++0x [temp.names]p3:
//
@@ -200,13 +200,18 @@ static prec::Level getBinOpPrecedence(tok::TokenKind Kind,
/// expression ',' assignment-expression
///
Parser::OwningExprResult Parser::ParseExpression() {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteOrdinaryName(CurScope);
+ ConsumeToken();
+ }
+
OwningExprResult LHS(ParseAssignmentExpression());
if (LHS.isInvalid()) return move(LHS);
return ParseRHSOfBinaryExpression(move(LHS), prec::Comma);
}
-/// This routine is called when the '@' is seen and consumed.
+/// This routine is called when the '@' is seen and consumed.
/// Current token is an Identifier and is not a 'try'. This
/// routine is necessary to disambiguate @try-statement from,
/// for example, @encode-expression.
@@ -277,11 +282,11 @@ Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc,
Parser::OwningExprResult Parser::ParseConstantExpression() {
// C++ [basic.def.odr]p2:
- // An expression is potentially evaluated unless it appears where an
+ // An expression is potentially evaluated unless it appears where an
// integral constant expression is required (see 5.19) [...].
EnterExpressionEvaluationContext Unevaluated(Actions,
Action::Unevaluated);
-
+
OwningExprResult LHS(ParseCastExpression(false));
if (LHS.isInvalid()) return move(LHS);
@@ -292,7 +297,7 @@ Parser::OwningExprResult Parser::ParseConstantExpression() {
/// LHS and has a precedence of at least MinPrec.
Parser::OwningExprResult
Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec) {
- unsigned NextTokPrec = getBinOpPrecedence(Tok.getKind(),
+ unsigned NextTokPrec = getBinOpPrecedence(Tok.getKind(),
GreaterThanIsOperator,
getLang().CPlusPlus0x);
SourceLocation ColonLoc;
@@ -407,11 +412,13 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec) {
/// due to member pointers.
///
Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
- bool isAddressOfOperand) {
+ bool isAddressOfOperand,
+ bool parseParenAsExprList){
bool NotCastExpr;
OwningExprResult Res = ParseCastExpression(isUnaryExpression,
isAddressOfOperand,
- NotCastExpr);
+ NotCastExpr,
+ parseParenAsExprList);
if (NotCastExpr)
Diag(Tok, diag::err_expected_expression);
return move(Res);
@@ -463,10 +470,10 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
/// assign-expr ')'
/// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
/// [GNU] '__null'
-/// [OBJC] '[' objc-message-expr ']'
+/// [OBJC] '[' objc-message-expr ']'
/// [OBJC] '@selector' '(' objc-selector-arg ')'
-/// [OBJC] '@protocol' '(' identifier ')'
-/// [OBJC] '@encode' '(' type-name ')'
+/// [OBJC] '@protocol' '(' identifier ')'
+/// [OBJC] '@encode' '(' type-name ')'
/// [OBJC] objc-string-literal
/// [C++] simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
/// [C++] typename-specifier '(' expression-list[opt] ')' [TODO]
@@ -530,11 +537,12 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
///
Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
bool isAddressOfOperand,
- bool &NotCastExpr) {
+ bool &NotCastExpr,
+ bool parseParenAsExprList){
OwningExprResult Res(Actions);
tok::TokenKind SavedKind = Tok.getKind();
NotCastExpr = false;
-
+
// This handles all of cast-expression, unary-expression, postfix-expression,
// and primary-expression. We handle them together like this for efficiency
// and to simplify handling of an expression starting with a '(' token: which
@@ -555,9 +563,9 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
SourceLocation LParenLoc = Tok.getLocation();
SourceLocation RParenLoc;
Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
- CastTy, RParenLoc);
+ parseParenAsExprList, CastTy, RParenLoc);
if (Res.isInvalid()) return move(Res);
-
+
switch (ParenExprType) {
case SimpleExpr: break; // Nothing else to do.
case CompoundStmt: break; // Nothing else to do.
@@ -605,23 +613,23 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
}
// Support 'Class.property' notation.
- // We don't use isTokObjCMessageIdentifierReceiver(), since it allows
+ // We don't use isTokObjCMessageIdentifierReceiver(), since it allows
// 'super' (which is inappropriate here).
- if (getLang().ObjC1 &&
- Actions.getTypeName(*Tok.getIdentifierInfo(),
+ if (getLang().ObjC1 &&
+ Actions.getTypeName(*Tok.getIdentifierInfo(),
Tok.getLocation(), CurScope) &&
NextToken().is(tok::period)) {
IdentifierInfo &ReceiverName = *Tok.getIdentifierInfo();
SourceLocation IdentLoc = ConsumeToken();
SourceLocation DotLoc = ConsumeToken();
-
+
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
return ExprError();
}
IdentifierInfo &PropertyName = *Tok.getIdentifierInfo();
SourceLocation PropertyLoc = ConsumeToken();
-
+
Res = Actions.ActOnClassPropertyRefExpr(ReceiverName, PropertyName,
IdentLoc, PropertyLoc);
// These can be followed by postfix-expr pieces.
@@ -739,6 +747,8 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw_char:
case tok::kw_wchar_t:
+ case tok::kw_char16_t:
+ case tok::kw_char32_t:
case tok::kw_bool:
case tok::kw_short:
case tok::kw_int:
@@ -794,7 +804,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
return ParseCXXNewExpression(true, CCLoc);
if (Tok.is(tok::kw_delete))
return ParseCXXDeleteExpression(true, CCLoc);
-
+
// This is not a type name or scope specifier, it is an invalid expression.
Diag(CCLoc, diag::err_expected_expression);
return ExprError();
@@ -810,9 +820,12 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
case tok::kw___is_class:
case tok::kw___is_enum:
case tok::kw___is_union:
+ case tok::kw___is_empty:
case tok::kw___is_polymorphic:
case tok::kw___is_abstract:
case tok::kw___has_trivial_constructor:
+ case tok::kw___has_trivial_copy:
+ case tok::kw___has_trivial_assign:
case tok::kw___has_trivial_destructor:
return ParseUnaryTypeTrait();
@@ -826,7 +839,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// These can be followed by postfix-expr pieces.
if (getLang().ObjC1)
return ParsePostfixExpressionSuffix(ParseObjCMessageExpression());
- // FALL THROUGH.
+ // FALL THROUGH.
default:
NotCastExpr = true;
return ExprError();
@@ -886,8 +899,14 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
Loc = ConsumeParen();
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteCall(CurScope, LHS.get(), 0, 0);
+ ConsumeToken();
+ }
+
if (Tok.isNot(tok::r_paren)) {
- if (ParseExpressionList(ArgExprs, CommaLocs)) {
+ if (ParseExpressionList(ArgExprs, CommaLocs, &Action::CodeCompleteCall,
+ LHS.get())) {
SkipUntil(tok::r_paren);
return ExprError();
}
@@ -898,7 +917,7 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
MatchRHSPunctuation(tok::r_paren, Loc);
return ExprError();
}
-
+
if (!LHS.isInvalid()) {
assert((ArgExprs.size() == 0 || ArgExprs.size()-1 == CommaLocs.size())&&
"Unexpected number of commas!");
@@ -906,33 +925,117 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
move_arg(ArgExprs), CommaLocs.data(),
Tok.getLocation());
}
-
+
ConsumeParen();
break;
}
- case tok::arrow: // postfix-expression: p-e '->' identifier
- case tok::period: { // postfix-expression: p-e '.' identifier
+ case tok::arrow:
+ case tok::period: {
+ // postfix-expression: p-e '->' template[opt] id-expression
+ // postfix-expression: p-e '.' template[opt] id-expression
tok::TokenKind OpKind = Tok.getKind();
SourceLocation OpLoc = ConsumeToken(); // Eat the "." or "->" token.
- if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_expected_ident);
- return ExprError();
+ CXXScopeSpec SS;
+ Action::TypeTy *ObjectType = 0;
+ if (getLang().CPlusPlus && !LHS.isInvalid()) {
+ LHS = Actions.ActOnStartCXXMemberReference(CurScope, move(LHS),
+ OpLoc, OpKind, ObjectType);
+ if (LHS.isInvalid())
+ break;
+ ParseOptionalCXXScopeSpecifier(SS, ObjectType, false);
}
- if (!LHS.isInvalid()) {
- LHS = Actions.ActOnMemberReferenceExpr(CurScope, move(LHS), OpLoc,
- OpKind, Tok.getLocation(),
- *Tok.getIdentifierInfo(),
- ObjCImpDecl);
+ if (Tok.is(tok::code_completion)) {
+ // Code completion for a member access expression.
+ Actions.CodeCompleteMemberReferenceExpr(CurScope, LHS.get(),
+ OpLoc, OpKind == tok::arrow);
+
+ ConsumeToken();
+ }
+
+ if (Tok.is(tok::identifier)) {
+ if (!LHS.isInvalid())
+ LHS = Actions.ActOnMemberReferenceExpr(CurScope, move(LHS), OpLoc,
+ OpKind, Tok.getLocation(),
+ *Tok.getIdentifierInfo(),
+ ObjCImpDecl, &SS);
+ ConsumeToken();
+ } else if (getLang().CPlusPlus && Tok.is(tok::tilde)) {
+ // We have a C++ pseudo-destructor or a destructor call, e.g., t.~T()
+
+ // Consume the tilde.
+ ConsumeToken();
+
+ if (!Tok.is(tok::identifier)) {
+ Diag(Tok, diag::err_expected_ident);
+ return ExprError();
+ }
+
+ if (!LHS.isInvalid())
+ LHS = Actions.ActOnDestructorReferenceExpr(CurScope, move(LHS),
+ OpLoc, OpKind,
+ Tok.getLocation(),
+ Tok.getIdentifierInfo(),
+ SS,
+ NextToken().is(tok::l_paren));
+ ConsumeToken();
+ } else if (getLang().CPlusPlus && Tok.is(tok::kw_operator)) {
+ // We have a reference to a member operator, e.g., t.operator int or
+ // t.operator+.
+ SourceLocation OperatorLoc = Tok.getLocation();
+
+ if (OverloadedOperatorKind Op = TryParseOperatorFunctionId()) {
+ if (!LHS.isInvalid())
+ LHS = Actions.ActOnOverloadedOperatorReferenceExpr(CurScope,
+ move(LHS), OpLoc,
+ OpKind,
+ OperatorLoc,
+ Op, &SS);
+ // TryParseOperatorFunctionId already consumed our token, so
+ // don't bother
+ } else if (TypeTy *ConvType = ParseConversionFunctionId()) {
+ if (!LHS.isInvalid())
+ LHS = Actions.ActOnConversionOperatorReferenceExpr(CurScope,
+ move(LHS), OpLoc,
+ OpKind,
+ OperatorLoc,
+ ConvType, &SS);
+ } else {
+ // Don't emit a diagnostic; ParseConversionFunctionId does it for us
+ return ExprError();
+ }
+ } else if (getLang().CPlusPlus && Tok.is(tok::annot_template_id)) {
+ // We have a reference to a member template along with explicitly-
+ // specified template arguments, e.g., t.f<int>.
+ TemplateIdAnnotation *TemplateId
+ = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+ if (!LHS.isInvalid()) {
+ ASTTemplateArgsPtr TemplateArgsPtr(Actions,
+ TemplateId->getTemplateArgs(),
+ TemplateId->getTemplateArgIsType(),
+ TemplateId->NumArgs);
+
+ LHS = Actions.ActOnMemberTemplateIdReferenceExpr(CurScope, move(LHS),
+ OpLoc, OpKind, SS,
+ TemplateTy::make(TemplateId->Template),
+ TemplateId->TemplateNameLoc,
+ TemplateId->LAngleLoc,
+ TemplateArgsPtr,
+ TemplateId->getTemplateArgLocations(),
+ TemplateId->RAngleLoc);
+ }
+ ConsumeToken();
+ } else {
+ Diag(Tok, diag::err_expected_ident);
+ return ExprError();
}
- ConsumeToken();
break;
}
case tok::plusplus: // postfix-expression: postfix-expression '++'
case tok::minusminus: // postfix-expression: postfix-expression '--'
if (!LHS.isInvalid()) {
- LHS = Actions.ActOnPostfixUnaryOp(CurScope, Tok.getLocation(),
+ LHS = Actions.ActOnPostfixUnaryOp(CurScope, Tok.getLocation(),
Tok.getKind(), move(LHS));
}
ConsumeToken();
@@ -963,13 +1066,13 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
bool &isCastExpr,
TypeTy *&CastTy,
SourceRange &CastRange) {
-
- assert((OpTok.is(tok::kw_typeof) || OpTok.is(tok::kw_sizeof) ||
+
+ assert((OpTok.is(tok::kw_typeof) || OpTok.is(tok::kw_sizeof) ||
OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof)) &&
"Not a typeof/sizeof/alignof expression!");
OwningExprResult Operand(Actions);
-
+
// If the operand doesn't start with an '(', it must be an expression.
if (Tok.isNot(tok::l_paren)) {
isCastExpr = false;
@@ -977,9 +1080,9 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
Diag(Tok,diag::err_expected_lparen_after_id) << OpTok.getIdentifierInfo();
return ExprError();
}
-
+
// C++0x [expr.sizeof]p1:
- // [...] The operand is either an expression, which is an unevaluated
+ // [...] The operand is either an expression, which is an unevaluated
// operand (Clause 5) [...]
//
// The GNU typeof and alignof extensions also behave as unevaluated
@@ -994,16 +1097,16 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
// expression.
ParenParseOption ExprType = CastExpr;
SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
-
+
// C++0x [expr.sizeof]p1:
- // [...] The operand is either an expression, which is an unevaluated
+ // [...] The operand is either an expression, which is an unevaluated
// operand (Clause 5) [...]
//
// The GNU typeof and alignof extensions also behave as unevaluated
// operands.
EnterExpressionEvaluationContext Unevaluated(Actions,
Action::Unevaluated);
- Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
+ Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/, false,
CastTy, RParenLoc);
CastRange = SourceRange(LParenLoc, RParenLoc);
@@ -1014,7 +1117,7 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
return ExprEmpty();
}
- // If this is a parenthesized expression, it is the start of a
+ // If this is a parenthesized expression, it is the start of a
// unary-expression, but doesn't include any postfix pieces. Parse these
// now if present.
Operand = ParsePostfixExpressionSuffix(move(Operand));
@@ -1039,7 +1142,7 @@ Parser::OwningExprResult Parser::ParseSizeofAlignofExpression() {
"Not a sizeof/alignof expression!");
Token OpTok = Tok;
ConsumeToken();
-
+
bool isCastExpr;
TypeTy *CastTy;
SourceRange CastRange;
@@ -1071,7 +1174,7 @@ Parser::OwningExprResult Parser::ParseSizeofAlignofExpression() {
/// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
/// assign-expr ')'
/// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
-///
+///
/// [GNU] offsetof-member-designator:
/// [GNU] identifier
/// [GNU] offsetof-member-designator '.' identifier
@@ -1123,7 +1226,7 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
SkipUntil(tok::r_paren);
return ExprError();
}
-
+
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
return ExprError();
@@ -1179,8 +1282,8 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
} else if (Ty.isInvalid()) {
Res = ExprError();
} else {
- Res = Actions.ActOnBuiltinOffsetOf(CurScope, StartLoc, TypeLoc,
- Ty.get(), &Comps[0],
+ Res = Actions.ActOnBuiltinOffsetOf(CurScope, StartLoc, TypeLoc,
+ Ty.get(), &Comps[0],
Comps.size(), ConsumeParen());
}
break;
@@ -1260,7 +1363,8 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
///
Parser::OwningExprResult
Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
- TypeTy *&CastTy, SourceLocation &RParenLoc) {
+ bool parseAsExprList, TypeTy *&CastTy,
+ SourceLocation &RParenLoc) {
assert(Tok.is(tok::l_paren) && "Not a paren expr!");
GreaterThanIsOperatorScope G(GreaterThanIsOperator, true);
SourceLocation OpenLoc = ConsumeParen();
@@ -1279,9 +1383,9 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
} else if (ExprType >= CompoundLiteral &&
isTypeIdInParens(isAmbiguousTypeId)) {
-
+
// Otherwise, this is a compound literal expression or cast expression.
-
+
// In C++, if the type-id is ambiguous we disambiguate based on context.
// If stopIfCastExpr is true the context is a typeof/sizeof/alignof
// in which case we should treat it as type-id.
@@ -1290,7 +1394,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
if (isAmbiguousTypeId && !stopIfCastExpr)
return ParseCXXAmbiguousParenExpression(ExprType, CastTy,
OpenLoc, RParenLoc);
-
+
TypeResult Ty = ParseTypeName();
// Match the ')'.
@@ -1320,14 +1424,25 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
// Parse the cast-expression that follows it next.
// TODO: For cast expression with CastTy.
- Result = ParseCastExpression(false);
+ Result = ParseCastExpression(false, false, true);
if (!Result.isInvalid())
- Result = Actions.ActOnCastExpr(OpenLoc, CastTy, RParenLoc,move(Result));
+ Result = Actions.ActOnCastExpr(CurScope, OpenLoc, CastTy, RParenLoc,
+ move(Result));
return move(Result);
}
Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
return ExprError();
+ } else if (parseAsExprList) {
+ // Parse the expression-list.
+ ExprVector ArgExprs(Actions);
+ CommaLocsTy CommaLocs;
+
+ if (!ParseExpressionList(ArgExprs, CommaLocs)) {
+ ExprType = SimpleExpr;
+ Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(),
+ move_arg(ArgExprs));
+ }
} else {
Result = ParseExpression();
ExprType = SimpleExpr;
@@ -1340,7 +1455,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
SkipUntil(tok::r_paren);
return ExprError();
}
-
+
if (Tok.is(tok::r_paren))
RParenLoc = ConsumeParen();
else
@@ -1401,8 +1516,19 @@ Parser::OwningExprResult Parser::ParseStringLiteralExpression() {
/// [C++] assignment-expression
/// [C++] expression-list , assignment-expression
///
-bool Parser::ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs) {
+bool Parser::ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs,
+ void (Action::*Completer)(Scope *S,
+ void *Data,
+ ExprTy **Args,
+ unsigned NumArgs),
+ void *Data) {
while (1) {
+ if (Tok.is(tok::code_completion)) {
+ if (Completer)
+ (Actions.*Completer)(CurScope, Data, Exprs.data(), Exprs.size());
+ ConsumeToken();
+ }
+
OwningExprResult Expr(ParseAssignmentExpression());
if (Expr.isInvalid())
return true;
@@ -1460,7 +1586,7 @@ Parser::OwningExprResult Parser::ParseBlockLiteralExpression() {
PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), CaretLoc,
"block literal parsing");
- // Enter a scope to hold everything within the block. This includes the
+ // Enter a scope to hold everything within the block. This includes the
// argument decls, decls within the compound expression, etc. This also
// allows determining whether a variable reference inside the block is
// within or outside of the block.
@@ -1470,7 +1596,7 @@ Parser::OwningExprResult Parser::ParseBlockLiteralExpression() {
// Inform sema that we are starting a block.
Actions.ActOnBlockStart(CaretLoc, CurScope);
-
+
// Parse the return type if present.
DeclSpec DS;
Declarator ParamInfo(DS, Declarator::BlockLiteralContext);
@@ -1508,12 +1634,13 @@ Parser::OwningExprResult Parser::ParseBlockLiteralExpression() {
ParseBlockId();
} else {
// Otherwise, pretend we saw (void).
- ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false,
+ ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false,
SourceLocation(),
0, 0, 0,
false, SourceLocation(),
false, 0, 0, 0,
- CaretLoc, ParamInfo),
+ CaretLoc, CaretLoc,
+ ParamInfo),
CaretLoc);
if (Tok.is(tok::kw___attribute)) {
@@ -1534,7 +1661,7 @@ Parser::OwningExprResult Parser::ParseBlockLiteralExpression() {
Actions.ActOnBlockError(CaretLoc, CurScope);
return ExprError();
}
-
+
OwningStmtResult Stmt(ParseCompoundStatementBody());
if (!Stmt.isInvalid())
Result = Actions.ActOnBlockStmtExpr(CaretLoc, move(Stmt), CurScope);
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 1220b2d27b4f..325f085a49d8 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -16,10 +16,11 @@
#include "clang/Parse/DeclSpec.h"
using namespace clang;
-/// ParseOptionalCXXScopeSpecifier - Parse global scope or
-/// nested-name-specifier if present. Returns true if a nested-name-specifier
-/// was parsed from the token stream. Note that this routine will not parse
-/// ::new or ::delete, it will just leave them in the token stream.
+/// \brief Parse global scope or nested-name-specifier if present.
+///
+/// Parses a C++ global scope specifier ('::') or nested-name-specifier (which
+/// may be preceded by '::'). Note that this routine will not parse ::new or
+/// ::delete; it will just leave them in the token stream.
///
/// '::'[opt] nested-name-specifier
/// '::'
@@ -28,9 +29,23 @@ using namespace clang;
/// type-name '::'
/// namespace-name '::'
/// nested-name-specifier identifier '::'
-/// nested-name-specifier 'template'[opt] simple-template-id '::' [TODO]
+/// nested-name-specifier 'template'[opt] simple-template-id '::'
+///
+///
+/// \param SS the scope specifier that will be set to the parsed
+/// nested-name-specifier (or empty)
+///
+/// \param ObjectType if this nested-name-specifier is being parsed following
+/// the "." or "->" of a member access expression, this parameter provides the
+/// type of the object whose members are being accessed.
///
-bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) {
+/// \param EnteringContext whether we will be entering into the context of
+/// the nested-name-specifier after parsing it.
+///
+/// \returns true if a scope specifier was parsed.
+bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
+ Action::TypeTy *ObjectType,
+ bool EnteringContext) {
assert(getLang().CPlusPlus &&
"Call sites of this function should be guarded by checking for C++");
@@ -48,7 +63,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) {
tok::TokenKind NextKind = NextToken().getKind();
if (NextKind == tok::kw_new || NextKind == tok::kw_delete)
return false;
-
+
// '::' - Global scope qualifier.
SourceLocation CCLoc = ConsumeToken();
SS.setBeginLoc(CCLoc);
@@ -58,21 +73,48 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) {
}
while (true) {
+ if (HasScopeSpecifier) {
+ // C++ [basic.lookup.classref]p5:
+ // If the qualified-id has the form
+ //
+ // ::class-name-or-namespace-name::...
+ //
+ // the class-name-or-namespace-name is looked up in global scope as a
+ // class-name or namespace-name.
+ //
+ // To implement this, we clear out the object type as soon as we've
+ // seen a leading '::' or part of a nested-name-specifier.
+ ObjectType = 0;
+
+ if (Tok.is(tok::code_completion)) {
+ // Code completion for a nested-name-specifier, where the code
+ // code completion token follows the '::'.
+ Actions.CodeCompleteQualifiedId(CurScope, SS, EnteringContext);
+ ConsumeToken();
+ }
+ }
+
// nested-name-specifier:
// nested-name-specifier 'template'[opt] simple-template-id '::'
// Parse the optional 'template' keyword, then make sure we have
// 'identifier <' after it.
if (Tok.is(tok::kw_template)) {
+ // If we don't have a scope specifier or an object type, this isn't a
+ // nested-name-specifier, since they aren't allowed to start with
+ // 'template'.
+ if (!HasScopeSpecifier && !ObjectType)
+ break;
+
SourceLocation TemplateKWLoc = ConsumeToken();
-
+
if (Tok.isNot(tok::identifier)) {
- Diag(Tok.getLocation(),
+ Diag(Tok.getLocation(),
diag::err_id_after_template_in_nested_name_spec)
<< SourceRange(TemplateKWLoc);
break;
}
-
+
if (NextToken().isNot(tok::less)) {
Diag(NextToken().getLocation(),
diag::err_less_after_template_name_in_nested_name_spec)
@@ -80,49 +122,51 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) {
<< SourceRange(TemplateKWLoc, Tok.getLocation());
break;
}
-
- TemplateTy Template
+
+ TemplateTy Template
= Actions.ActOnDependentTemplateName(TemplateKWLoc,
*Tok.getIdentifierInfo(),
- Tok.getLocation(), SS);
+ Tok.getLocation(), SS,
+ ObjectType);
+ if (!Template)
+ break;
if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
&SS, TemplateKWLoc, false))
break;
-
+
continue;
}
-
+
if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) {
- // We have
+ // We have
//
// simple-template-id '::'
//
// So we need to check whether the simple-template-id is of the
// right kind (it should name a type or be dependent), and then
// convert it into a type within the nested-name-specifier.
- TemplateIdAnnotation *TemplateId
+ TemplateIdAnnotation *TemplateId
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
- if (TemplateId->Kind == TNK_Type_template ||
+ if (TemplateId->Kind == TNK_Type_template ||
TemplateId->Kind == TNK_Dependent_template_name) {
AnnotateTemplateIdTokenAsType(&SS);
- SS.setScopeRep(0);
- assert(Tok.is(tok::annot_typename) &&
+ assert(Tok.is(tok::annot_typename) &&
"AnnotateTemplateIdTokenAsType isn't working");
Token TypeToken = Tok;
ConsumeToken();
assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
SourceLocation CCLoc = ConsumeToken();
-
+
if (!HasScopeSpecifier) {
SS.setBeginLoc(TypeToken.getLocation());
HasScopeSpecifier = true;
}
-
+
if (TypeToken.getAnnotationValue())
SS.setScopeRep(
- Actions.ActOnCXXNestedNameSpecifier(CurScope, SS,
+ Actions.ActOnCXXNestedNameSpecifier(CurScope, SS,
TypeToken.getAnnotationValue(),
TypeToken.getAnnotationRange(),
CCLoc));
@@ -131,7 +175,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) {
SS.setEndLoc(CCLoc);
continue;
}
-
+
assert(false && "FIXME: Only type template names supported here");
}
@@ -154,27 +198,32 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) {
SourceLocation IdLoc = ConsumeToken();
assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
SourceLocation CCLoc = ConsumeToken();
-
+
if (!HasScopeSpecifier) {
SS.setBeginLoc(IdLoc);
HasScopeSpecifier = true;
}
-
+
if (SS.isInvalid())
continue;
-
+
SS.setScopeRep(
- Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, II));
+ Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, II,
+ ObjectType, EnteringContext));
SS.setEndLoc(CCLoc);
continue;
}
-
+
// nested-name-specifier:
// type-name '<'
if (Next.is(tok::less)) {
TemplateTy Template;
- if (TemplateNameKind TNK = Actions.isTemplateName(II, CurScope,
- Template, &SS)) {
+ if (TemplateNameKind TNK = Actions.isTemplateName(CurScope, II,
+ Tok.getLocation(),
+ &SS,
+ ObjectType,
+ EnteringContext,
+ Template)) {
// We have found a template name, so annotate this this token
// with a template-id annotation. We do not permit the
// template-id to be translated into a type annotation,
@@ -192,7 +241,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) {
// nested-name-specifier, so we're done.
break;
}
-
+
return HasScopeSpecifier;
}
@@ -257,7 +306,7 @@ Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
// '::' unqualified-id
//
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS);
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
// unqualified-id:
// identifier
@@ -295,17 +344,17 @@ Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
}
case tok::annot_template_id: {
- TemplateIdAnnotation *TemplateId
+ TemplateIdAnnotation *TemplateId
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
assert((TemplateId->Kind == TNK_Function_template ||
TemplateId->Kind == TNK_Dependent_template_name) &&
"A template type name is not an ID expression");
- ASTTemplateArgsPtr TemplateArgsPtr(Actions,
+ ASTTemplateArgsPtr TemplateArgsPtr(Actions,
TemplateId->getTemplateArgs(),
TemplateId->getTemplateArgIsType(),
TemplateId->NumArgs);
-
+
OwningExprResult Result
= Actions.ActOnTemplateIdExpr(TemplateTy::make(TemplateId->Template),
TemplateId->TemplateNameLoc,
@@ -361,11 +410,11 @@ Parser::OwningExprResult Parser::ParseCXXCasts() {
return ExprError();
OwningExprResult Result = ParseExpression();
-
+
// Match the ')'.
if (Result.isInvalid())
SkipUntil(tok::r_paren);
-
+
if (Tok.is(tok::r_paren))
RParenLoc = ConsumeParen();
else
@@ -413,11 +462,11 @@ Parser::OwningExprResult Parser::ParseCXXTypeid() {
Ty.get(), RParenLoc);
} else {
// C++0x [expr.typeid]p3:
- // When typeid is applied to an expression other than an lvalue of a
- // polymorphic class type [...] The expression is an unevaluated
+ // When typeid is applied to an expression other than an lvalue of a
+ // polymorphic class type [...] The expression is an unevaluated
// operand (Clause 5).
//
- // Note that we can't tell whether the expression is an lvalue of a
+ // Note that we can't tell whether the expression is an lvalue of a
// polymorphic class type until after we've parsed the expression, so
// we the expression is potentially potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(Actions,
@@ -516,6 +565,10 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
// Match the ')'.
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
+ // TypeRep could be null, if it references an invalid typedef.
+ if (!TypeRep)
+ return ExprError();
+
assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
"Unexpected number of commas!");
return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
@@ -606,58 +659,65 @@ Parser::OwningExprResult Parser::ParseCXXCondition() {
void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
DS.SetRangeStart(Tok.getLocation());
const char *PrevSpec;
+ unsigned DiagID;
SourceLocation Loc = Tok.getLocation();
-
+
switch (Tok.getKind()) {
case tok::identifier: // foo::bar
case tok::coloncolon: // ::foo::bar
assert(0 && "Annotation token should already be formed!");
- default:
+ default:
assert(0 && "Not a simple-type-specifier token!");
abort();
// type-name
case tok::annot_typename: {
- DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
+ DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID,
Tok.getAnnotationValue());
break;
}
-
+
// builtin types
case tok::kw_short:
- DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec);
+ DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID);
break;
case tok::kw_long:
- DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec);
+ DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, DiagID);
break;
case tok::kw_signed:
- DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec);
+ DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID);
break;
case tok::kw_unsigned:
- DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec);
+ DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec, DiagID);
break;
case tok::kw_void:
- DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec);
+ DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID);
break;
case tok::kw_char:
- DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec);
+ DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID);
break;
case tok::kw_int:
- DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec);
+ DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID);
break;
case tok::kw_float:
- DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec);
+ DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID);
break;
case tok::kw_double:
- DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec);
+ DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID);
break;
case tok::kw_wchar_t:
- DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec);
+ DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_char16_t:
+ DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID);
+ break;
+ case tok::kw_char32_t:
+ DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID);
break;
case tok::kw_bool:
- DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec);
+ DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID);
break;
-
+
// GNU typeof support.
case tok::kw_typeof:
ParseTypeofSpecifier(DS);
@@ -686,15 +746,16 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
DS.SetRangeStart(Tok.getLocation());
const char *PrevSpec = 0;
- int isInvalid = 0;
+ unsigned DiagID;
+ bool isInvalid = 0;
// Parse one or more of the type specifiers.
- if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec)) {
+ if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID)) {
Diag(Tok, diag::err_operator_missing_type_specifier);
return true;
}
-
- while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec)) ;
+
+ while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID)) ;
return false;
}
@@ -774,6 +835,18 @@ Parser::TryParseOperatorFunctionId(SourceLocation *EndLoc) {
*EndLoc = Loc;
return OO_Subscript;
+ case tok::code_completion: {
+ // Code completion for the operator name.
+ Actions.CodeCompleteOperatorName(CurScope);
+
+ // Consume the 'operator' token, then replace the code-completion token
+ // with an 'operator' token and try again.
+ SourceLocation OperatorLoc = ConsumeToken();
+ Tok.setLocation(OperatorLoc);
+ Tok.setKind(tok::kw_operator);
+ return TryParseOperatorFunctionId(EndLoc);
+ }
+
default:
return OO_None;
}
@@ -824,7 +897,7 @@ Parser::TypeTy *Parser::ParseConversionFunctionId(SourceLocation *EndLoc) {
/// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
/// memory in a typesafe manner and call constructors.
-///
+///
/// This method is called to parse the new expression after the optional :: has
/// been already parsed. If the :: was present, "UseGlobal" is true and "Start"
/// is its location. Otherwise, "Start" is the location of the 'new' token.
@@ -966,7 +1039,7 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) {
SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc);
D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
- Size.release(), LLoc),
+ Size.release(), LLoc, RLoc),
RLoc);
if (RLoc.isInvalid())
@@ -1033,8 +1106,7 @@ Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, move(Operand));
}
-static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind)
-{
+static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
switch(kind) {
default: assert(false && "Not a known unary type trait.");
case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign;
@@ -1062,8 +1134,7 @@ static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind)
/// primary-expression:
/// [GNU] unary-type-trait '(' type-id ')'
///
-Parser::OwningExprResult Parser::ParseUnaryTypeTrait()
-{
+Parser::OwningExprResult Parser::ParseUnaryTypeTrait() {
UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind());
SourceLocation Loc = ConsumeToken();
@@ -1118,7 +1189,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
// parsing a cast-expression), and then we re-introduce the cached tokens
// into the token stream and parse them appropriately.
- ParenParseOption ParseAs;
+ ParenParseOption ParseAs;
CachedTokens Toks;
// Store the tokens of the parentheses. We will parse them after we determine
@@ -1142,7 +1213,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
// will be consumed.
Result = ParseCastExpression(false/*isUnaryExpression*/,
false/*isAddressofOperand*/,
- NotCastExpr);
+ NotCastExpr, false);
}
// If we parsed a cast-expression, it's really a type-id, otherwise it's
@@ -1150,7 +1221,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
ParseAs = NotCastExpr ? SimpleExpr : CastExpr;
}
- // The current token should go after the cached tokens.
+ // The current token should go after the cached tokens.
Toks.push_back(Tok);
// Re-enter the stored parenthesized tokens into the token stream, so we may
// parse them now.
@@ -1173,7 +1244,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
ExprType = CompoundLiteral;
return ParseCompoundLiteralExpression(Ty.get(), LParenLoc, RParenLoc);
}
-
+
// We parsed '(' type-id ')' and the thing after it wasn't a '{'.
assert(ParseAs == CastExpr);
@@ -1184,10 +1255,11 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
// Result is what ParseCastExpression returned earlier.
if (!Result.isInvalid())
- Result = Actions.ActOnCastExpr(LParenLoc, CastTy, RParenLoc,move(Result));
+ Result = Actions.ActOnCastExpr(CurScope, LParenLoc, CastTy, RParenLoc,
+ move(Result));
return move(Result);
}
-
+
// Not a compound literal, and not followed by a cast-expression.
assert(ParseAs == SimpleExpr);
@@ -1201,7 +1273,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
SkipUntil(tok::r_paren);
return ExprError();
}
-
+
if (Tok.is(tok::r_paren))
RParenLoc = ConsumeParen();
else
diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp
index bbc2124e5986..6ab23fd42ddc 100644
--- a/lib/Parse/ParseInit.cpp
+++ b/lib/Parse/ParseInit.cpp
@@ -20,7 +20,7 @@ using namespace clang;
/// MayBeDesignationStart - Return true if this token might be the start of a
/// designator. If we can tell it is impossible that it is a designator, return
-/// false.
+/// false.
static bool MayBeDesignationStart(tok::TokenKind K, Preprocessor &PP) {
switch (K) {
default: return false;
@@ -70,46 +70,46 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
NewSyntax += " = ";
SourceLocation NameLoc = ConsumeToken(); // Eat the identifier.
-
+
assert(Tok.is(tok::colon) && "MayBeDesignationStart not working properly!");
SourceLocation ColonLoc = ConsumeToken();
Diag(Tok, diag::ext_gnu_old_style_field_designator)
- << CodeModificationHint::CreateReplacement(SourceRange(NameLoc,
+ << CodeModificationHint::CreateReplacement(SourceRange(NameLoc,
ColonLoc),
NewSyntax);
Designation D;
D.AddDesignator(Designator::getField(FieldName, SourceLocation(), NameLoc));
- return Actions.ActOnDesignatedInitializer(D, ColonLoc, true,
+ return Actions.ActOnDesignatedInitializer(D, ColonLoc, true,
ParseInitializer());
}
-
+
// Desig - This is initialized when we see our first designator. We may have
// an objc message send with no designator, so we don't want to create this
// eagerly.
Designation Desig;
-
+
// Parse each designator in the designator list until we find an initializer.
while (Tok.is(tok::period) || Tok.is(tok::l_square)) {
if (Tok.is(tok::period)) {
// designator: '.' identifier
SourceLocation DotLoc = ConsumeToken();
-
+
if (Tok.isNot(tok::identifier)) {
Diag(Tok.getLocation(), diag::err_expected_field_designator);
return ExprError();
}
-
+
Desig.AddDesignator(Designator::getField(Tok.getIdentifierInfo(), DotLoc,
Tok.getLocation()));
ConsumeToken(); // Eat the identifier.
continue;
}
-
+
// We must have either an array designator now or an objc message send.
assert(Tok.is(tok::l_square) && "Unexpected token!");
-
+
// Handle the two forms of array designator:
// array-designator: '[' constant-expression ']'
// array-designator: '[' constant-expression '...' constant-expression ']'
@@ -123,14 +123,14 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
// [4][foo bar] -> obsolete GNU designation with objc message send.
//
SourceLocation StartLoc = ConsumeBracket();
-
+
// If Objective-C is enabled and this is a typename or other identifier
// receiver, parse this as a message send expression.
if (getLang().ObjC1 && isTokObjCMessageIdentifierReceiver()) {
// If we have exactly one array designator, this used the GNU
// 'designation: array-designator' extension, otherwise there should be no
// designators at all!
- if (Desig.getNumDesignators() == 1 &&
+ if (Desig.getNumDesignators() == 1 &&
(Desig.getDesignator(0).isArrayDesignator() ||
Desig.getDesignator(0).isArrayRangeDesignator()))
Diag(StartLoc, diag::ext_gnu_missing_equal_designator);
@@ -151,18 +151,18 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
SkipUntil(tok::r_square);
return move(Idx);
}
-
+
// Given an expression, we could either have a designator (if the next
// tokens are '...' or ']' or an objc message send. If this is an objc
- // message send, handle it now. An objc-message send is the start of
+ // message send, handle it now. An objc-message send is the start of
// an assignment-expression production.
- if (getLang().ObjC1 && Tok.isNot(tok::ellipsis) &&
+ if (getLang().ObjC1 && Tok.isNot(tok::ellipsis) &&
Tok.isNot(tok::r_square)) {
-
+
// If we have exactly one array designator, this used the GNU
// 'designation: array-designator' extension, otherwise there should be no
// designators at all!
- if (Desig.getNumDesignators() == 1 &&
+ if (Desig.getNumDesignators() == 1 &&
(Desig.getDesignator(0).isArrayDesignator() ||
Desig.getDesignator(0).isArrayRangeDesignator()))
Diag(StartLoc, diag::ext_gnu_missing_equal_designator);
@@ -213,7 +213,7 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {
// an initializer. If we have exactly one array designator, this
// is the GNU 'designation: array-designator' extension. Otherwise, it is a
// parse error.
- if (Desig.getNumDesignators() == 1 &&
+ if (Desig.getNumDesignators() == 1 &&
(Desig.getDesignator(0).isArrayDesignator() ||
Desig.getDesignator(0).isArrayRangeDesignator())) {
Diag(Tok, diag::ext_gnu_missing_equal_designator)
@@ -267,13 +267,13 @@ Parser::OwningExprResult Parser::ParseBraceInitializer() {
SubElt = ParseInitializerWithPotentialDesignator();
else
SubElt = ParseInitializer();
-
+
// If we couldn't parse the subelement, bail out.
if (!SubElt.isInvalid()) {
InitExprs.push_back(SubElt.release());
} else {
InitExprsOk = false;
-
+
// We have two ways to try to recover from this error: if the code looks
// gramatically ok (i.e. we have a comma coming up) try to continue
// parsing the rest of the initializer. This allows us to emit
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 013e26b891e1..1d29f319c584 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -29,7 +29,7 @@ using namespace clang;
/// [OBJC] '@' 'end'
Parser::DeclPtrTy Parser::ParseObjCAtDirectives() {
SourceLocation AtLoc = ConsumeToken(); // the "@"
-
+
switch (Tok.getObjCKeywordID()) {
case tok::objc_class:
return ParseObjCAtClassDeclaration(AtLoc);
@@ -55,13 +55,13 @@ Parser::DeclPtrTy Parser::ParseObjCAtDirectives() {
}
///
-/// objc-class-declaration:
+/// objc-class-declaration:
/// '@' 'class' identifier-list ';'
-///
+///
Parser::DeclPtrTy Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
ConsumeToken(); // the identifier "class"
llvm::SmallVector<IdentifierInfo *, 8> ClassNames;
-
+
while (1) {
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
@@ -70,17 +70,17 @@ Parser::DeclPtrTy Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
}
ClassNames.push_back(Tok.getIdentifierInfo());
ConsumeToken();
-
+
if (Tok.isNot(tok::comma))
break;
-
+
ConsumeToken();
}
-
+
// Consume the ';'.
if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
return DeclPtrTy();
-
+
return Actions.ActOnForwardClassDeclaration(atLoc,
&ClassNames[0], ClassNames.size());
}
@@ -91,14 +91,14 @@ Parser::DeclPtrTy Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
/// objc-category-interface
///
/// objc-class-interface:
-/// '@' 'interface' identifier objc-superclass[opt]
+/// '@' 'interface' identifier objc-superclass[opt]
/// objc-protocol-refs[opt]
-/// objc-class-instance-variables[opt]
+/// objc-class-instance-variables[opt]
/// objc-interface-decl-list
/// @end
///
/// objc-category-interface:
-/// '@' 'interface' identifier '(' identifier[opt] ')'
+/// '@' 'interface' identifier '(' identifier[opt] ')'
/// objc-protocol-refs[opt]
/// objc-interface-decl-list
/// @end
@@ -118,7 +118,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
assert(Tok.isObjCAtKeyword(tok::objc_interface) &&
"ParseObjCAtInterfaceDeclaration(): Expected @interface");
ConsumeToken(); // the "interface" identifier
-
+
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident); // missing class or category name.
return DeclPtrTy();
@@ -126,12 +126,12 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
// We have a class or category name - consume it.
IdentifierInfo *nameId = Tok.getIdentifierInfo();
SourceLocation nameLoc = ConsumeToken();
-
+
if (Tok.is(tok::l_paren)) { // we have a category.
SourceLocation lparenLoc = ConsumeParen();
SourceLocation categoryLoc, rparenLoc;
IdentifierInfo *categoryId = 0;
-
+
// For ObjC2, the category name is optional (not an error).
if (Tok.is(tok::identifier)) {
categoryId = Tok.getIdentifierInfo();
@@ -146,25 +146,27 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
return DeclPtrTy();
}
rparenLoc = ConsumeParen();
-
+
// Next, we need to check for any protocol references.
- SourceLocation EndProtoLoc;
+ SourceLocation LAngleLoc, EndProtoLoc;
llvm::SmallVector<DeclPtrTy, 8> ProtocolRefs;
+ llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
if (Tok.is(tok::less) &&
- ParseObjCProtocolReferences(ProtocolRefs, true, EndProtoLoc))
+ ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
+ LAngleLoc, EndProtoLoc))
return DeclPtrTy();
-
+
if (attrList) // categories don't support attributes.
Diag(Tok, diag::err_objc_no_attributes_on_category);
-
+
DeclPtrTy CategoryType =
- Actions.ActOnStartCategoryInterface(atLoc,
+ Actions.ActOnStartCategoryInterface(atLoc,
nameId, nameLoc,
categoryId, categoryLoc,
ProtocolRefs.data(),
ProtocolRefs.size(),
EndProtoLoc);
-
+
ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword);
return CategoryType;
}
@@ -183,17 +185,19 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
}
// Next, we need to check for any protocol references.
llvm::SmallVector<Action::DeclPtrTy, 8> ProtocolRefs;
- SourceLocation EndProtoLoc;
+ llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
+ SourceLocation LAngleLoc, EndProtoLoc;
if (Tok.is(tok::less) &&
- ParseObjCProtocolReferences(ProtocolRefs, true, EndProtoLoc))
+ ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true,
+ LAngleLoc, EndProtoLoc))
return DeclPtrTy();
-
- DeclPtrTy ClsType =
- Actions.ActOnStartClassInterface(atLoc, nameId, nameLoc,
+
+ DeclPtrTy ClsType =
+ Actions.ActOnStartClassInterface(atLoc, nameId, nameLoc,
superClassId, superClassLoc,
ProtocolRefs.data(), ProtocolRefs.size(),
EndProtoLoc, attrList);
-
+
if (Tok.is(tok::l_brace))
ParseObjCClassInstanceVariables(ClsType, atLoc);
@@ -219,13 +223,13 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
llvm::SmallVector<DeclPtrTy, 16> allProperties;
llvm::SmallVector<DeclGroupPtrTy, 8> allTUVariables;
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
-
+
SourceLocation AtEndLoc;
while (1) {
// If this is a method prototype, parse it.
if (Tok.is(tok::minus) || Tok.is(tok::plus)) {
- DeclPtrTy methodPrototype =
+ DeclPtrTy methodPrototype =
ParseObjCMethodPrototype(interfaceDecl, MethodImplKind);
allMethods.push_back(methodPrototype);
// Consume the ';' here, since ParseObjCMethodPrototype() is re-used for
@@ -234,17 +238,17 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
"", tok::semi);
continue;
}
-
+
// Ignore excess semicolons.
if (Tok.is(tok::semi)) {
ConsumeToken();
continue;
}
-
+
// If we got to the end of the file, exit the loop.
if (Tok.is(tok::eof))
break;
-
+
// If we don't have an @ directive, parse it as a function definition.
if (Tok.isNot(tok::at)) {
// The code below does not consume '}'s because it is afraid of eating the
@@ -252,22 +256,22 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
// erroneous r_brace would cause an infinite loop if not handled here.
if (Tok.is(tok::r_brace))
break;
-
+
// FIXME: as the name implies, this rule allows function definitions.
// We could pass a flag or check for functions during semantic analysis.
allTUVariables.push_back(ParseDeclarationOrFunctionDefinition());
continue;
}
-
+
// Otherwise, we have an @ directive, eat the @.
SourceLocation AtLoc = ConsumeToken(); // the "@"
tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID();
-
+
if (DirectiveKind == tok::objc_end) { // @end -> terminate list
AtEndLoc = AtLoc;
break;
}
-
+
// Eat the identifier.
ConsumeToken();
@@ -281,7 +285,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
// Skip until we see an '@' or '}' or ';'.
SkipUntil(tok::r_brace, tok::at);
break;
-
+
case tok::objc_required:
case tok::objc_optional:
// This is only valid on protocols.
@@ -291,24 +295,24 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
else
MethodImplKind = DirectiveKind;
break;
-
+
case tok::objc_property:
if (!getLang().ObjC2)
Diag(AtLoc, diag::err_objc_propertoes_require_objc2);
ObjCDeclSpec OCDS;
- // Parse property attribute list, if any.
+ // Parse property attribute list, if any.
if (Tok.is(tok::l_paren))
ParseObjCPropertyAttribute(OCDS);
-
+
// Parse all the comma separated declarators.
DeclSpec DS;
llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators;
ParseStructDeclaration(DS, FieldDeclarators);
-
+
ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list, "",
tok::at);
-
+
// Convert them all to property declarations.
for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) {
FieldDeclarator &FD = FieldDeclarators[i];
@@ -322,12 +326,12 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
<< FD.D.getSourceRange();
continue;
}
-
+
// Install the property declarator into interfaceDecl.
IdentifierInfo *SelName =
OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();
-
- Selector GetterSel =
+
+ Selector GetterSel =
PP.getSelectorTable().getNullarySelector(SelName);
IdentifierInfo *SetterName = OCDS.getSetterName();
Selector SetterSel;
@@ -340,7 +344,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
bool isOverridingProperty = false;
DeclPtrTy Property = Actions.ActOnProperty(CurScope, AtLoc, FD, OCDS,
GetterSel, SetterSel,
- interfaceDecl,
+ interfaceDecl,
&isOverridingProperty,
MethodImplKind);
if (!isOverridingProperty)
@@ -356,11 +360,11 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
ConsumeToken(); // the "end" identifier
else
Diag(Tok, diag::err_objc_missing_end);
-
+
// Insert collected methods declarations into the @interface object.
// This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
Actions.ActOnAtEnd(AtEndLoc, interfaceDecl,
- allMethods.data(), allMethods.size(),
+ allMethods.data(), allMethods.size(),
allProperties.data(), allProperties.size(),
allTUVariables.data(), allTUVariables.size());
}
@@ -384,18 +388,22 @@ void Parser::ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl,
void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
assert(Tok.getKind() == tok::l_paren);
SourceLocation LHSLoc = ConsumeParen(); // consume '('
-
+
while (1) {
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteObjCProperty(CurScope, DS);
+ ConsumeToken();
+ }
const IdentifierInfo *II = Tok.getIdentifierInfo();
-
+
// If this is not an identifier at all, bail out early.
if (II == 0) {
MatchRHSPunctuation(tok::r_paren, LHSLoc);
return;
}
-
+
SourceLocation AttrName = ConsumeToken(); // consume last attribute name
-
+
if (II->isStr("readonly"))
DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readonly);
else if (II->isStr("assign"))
@@ -413,18 +421,18 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
if (ExpectAndConsume(tok::equal, diag::err_objc_expected_equal, "",
tok::r_paren))
return;
-
+
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
SkipUntil(tok::r_paren);
return;
}
-
+
if (II->getName()[0] == 's') {
DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter);
DS.setSetterName(Tok.getIdentifierInfo());
ConsumeToken(); // consume method name
-
+
if (ExpectAndConsume(tok::colon, diag::err_expected_colon, "",
tok::r_paren))
return;
@@ -438,18 +446,18 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
SkipUntil(tok::r_paren);
return;
}
-
+
if (Tok.isNot(tok::comma))
break;
-
+
ConsumeToken();
}
-
+
MatchRHSPunctuation(tok::r_paren, LHSLoc);
}
/// objc-method-proto:
-/// objc-instance-method objc-method-decl objc-method-attributes[opt]
+/// objc-instance-method objc-method-decl objc-method-attributes[opt]
/// objc-class-method objc-method-decl objc-method-attributes[opt]
///
/// objc-instance-method: '-'
@@ -458,13 +466,13 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
/// objc-method-attributes: [OBJC2]
/// __attribute__((deprecated))
///
-Parser::DeclPtrTy Parser::ParseObjCMethodPrototype(DeclPtrTy IDecl,
+Parser::DeclPtrTy Parser::ParseObjCMethodPrototype(DeclPtrTy IDecl,
tok::ObjCKeywordKind MethodImplKind) {
assert((Tok.is(tok::minus) || Tok.is(tok::plus)) && "expected +/-");
- tok::TokenKind methodType = Tok.getKind();
+ tok::TokenKind methodType = Tok.getKind();
SourceLocation mLoc = ConsumeToken();
-
+
DeclPtrTy MDecl = ParseObjCMethodDecl(mLoc, methodType, IDecl,MethodImplKind);
// Since this rule is used for both method declarations and definitions,
// the caller is (optionally) responsible for consuming the ';'.
@@ -564,7 +572,7 @@ bool Parser::isTokIdentifier_in() const {
// FIXME: May have to do additional look-ahead to only allow for
// valid tokens following an 'in'; such as an identifier, unary operators,
// '[' etc.
- return (getLang().ObjC2 && Tok.is(tok::identifier) &&
+ return (getLang().ObjC2 && Tok.is(tok::identifier) &&
Tok.getIdentifierInfo() == ObjCTypeQuals[objc_in]);
}
@@ -580,12 +588,12 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS) {
while (1) {
if (Tok.isNot(tok::identifier))
return;
-
+
const IdentifierInfo *II = Tok.getIdentifierInfo();
for (unsigned i = 0; i != objc_NumQuals; ++i) {
if (II != ObjCTypeQuals[i])
continue;
-
+
ObjCDeclSpec::ObjCDeclQualifier Qual;
switch (i) {
default: assert(0 && "Unknown decl qualifier");
@@ -601,7 +609,7 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS) {
II = 0;
break;
}
-
+
// If this wasn't a recognized qualifier, bail out.
if (II) return;
}
@@ -613,10 +621,10 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS) {
///
Parser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS) {
assert(Tok.is(tok::l_paren) && "expected (");
-
+
SourceLocation LParenLoc = ConsumeParen();
SourceLocation TypeStartLoc = Tok.getLocation();
-
+
// Parse type qualifiers, in, inout, etc.
ParseObjCTypeQualifierList(DS);
@@ -626,7 +634,7 @@ Parser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS) {
if (!TypeSpec.isInvalid())
Ty = TypeSpec.get();
}
-
+
if (Tok.is(tok::r_paren))
ConsumeParen();
else if (Tok.getLocation() == TypeStartLoc) {
@@ -648,7 +656,7 @@ Parser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS) {
/// objc-type-name objc-keyword-selector objc-parmlist[opt]
///
/// objc-keyword-selector:
-/// objc-keyword-decl
+/// objc-keyword-decl
/// objc-keyword-selector objc-keyword-decl
///
/// objc-keyword-decl:
@@ -678,7 +686,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
ObjCDeclSpec DSRet;
if (Tok.is(tok::l_paren))
ReturnType = ParseObjCTypeName(DSRet);
-
+
SourceLocation selLoc;
IdentifierInfo *SelIdent = ParseObjCSelectorPiece(selLoc);
@@ -690,14 +698,14 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
SkipUntil(tok::r_brace);
return DeclPtrTy();
}
-
+
llvm::SmallVector<Declarator, 8> CargNames;
if (Tok.isNot(tok::colon)) {
// If attributes exist after the method, parse them.
AttributeList *MethodAttrs = 0;
- if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
+ if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
MethodAttrs = ParseAttributes();
-
+
Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
return Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(),
mType, IDecl, DSRet, ReturnType, Sel,
@@ -707,17 +715,17 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
llvm::SmallVector<Action::ObjCArgInfo, 12> ArgInfos;
-
+
while (1) {
Action::ObjCArgInfo ArgInfo;
-
+
// Each iteration parses a single keyword argument.
if (Tok.isNot(tok::colon)) {
Diag(Tok, diag::err_expected_colon);
break;
}
ConsumeToken(); // Eat the ':'.
-
+
ArgInfo.Type = 0;
if (Tok.is(tok::l_paren)) // Parse the argument type if present.
ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec);
@@ -731,11 +739,11 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
Diag(Tok, diag::err_expected_ident); // missing argument name.
break;
}
-
+
ArgInfo.Name = Tok.getIdentifierInfo();
ArgInfo.NameLoc = Tok.getLocation();
ConsumeToken(); // Eat the identifier.
-
+
ArgInfos.push_back(ArgInfo);
KeyIdents.push_back(SelIdent);
@@ -746,9 +754,9 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
break;
// We have a selector or a colon, continue parsing.
}
-
+
bool isVariadic = false;
-
+
// Parse the (optional) parameter list.
while (Tok.is(tok::comma)) {
ConsumeToken();
@@ -759,18 +767,18 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
}
DeclSpec DS;
ParseDeclarationSpecifiers(DS);
- // Parse the declarator.
+ // Parse the declarator.
Declarator ParmDecl(DS, Declarator::PrototypeContext);
ParseDeclarator(ParmDecl);
CargNames.push_back(ParmDecl);
}
-
+
// FIXME: Add support for optional parmameter list...
// If attributes exist after the method, parse them.
AttributeList *MethodAttrs = 0;
- if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
+ if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
MethodAttrs = ParseAttributes();
-
+
if (KeyIdents.size() == 0)
return DeclPtrTy();
Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),
@@ -786,13 +794,15 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
///
bool Parser::
ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &Protocols,
- bool WarnOnDeclarations, SourceLocation &EndLoc) {
+ llvm::SmallVectorImpl<SourceLocation> &ProtocolLocs,
+ bool WarnOnDeclarations,
+ SourceLocation &LAngleLoc, SourceLocation &EndLoc) {
assert(Tok.is(tok::less) && "expected <");
-
- ConsumeToken(); // the "<"
-
+
+ LAngleLoc = ConsumeToken(); // the "<"
+
llvm::SmallVector<IdentifierLocPair, 8> ProtocolIdents;
-
+
while (1) {
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
@@ -801,21 +811,22 @@ ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &Protocols,
}
ProtocolIdents.push_back(std::make_pair(Tok.getIdentifierInfo(),
Tok.getLocation()));
+ ProtocolLocs.push_back(Tok.getLocation());
ConsumeToken();
-
+
if (Tok.isNot(tok::comma))
break;
ConsumeToken();
}
-
+
// Consume the '>'.
if (Tok.isNot(tok::greater)) {
Diag(Tok, diag::err_expected_greater);
return true;
}
-
+
EndLoc = ConsumeAnyToken();
-
+
// Convert the list of protocols identifiers into a list of protocol decls.
Actions.FindProtocolDeclaration(WarnOnDeclarations,
&ProtocolIdents[0], ProtocolIdents.size(),
@@ -841,7 +852,7 @@ ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &Protocols,
/// @package [OBJC2]
///
/// objc-instance-variable-decl:
-/// struct-declaration
+/// struct-declaration
///
void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
SourceLocation atLoc) {
@@ -852,19 +863,19 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope);
SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
-
+
tok::ObjCKeywordKind visibility = tok::objc_protected;
// While we still have something to read, read the instance variables.
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
// Each iteration of this loop reads one objc-instance-variable-decl.
-
+
// Check for extraneous top-level semicolon.
if (Tok.is(tok::semi)) {
Diag(Tok, diag::ext_extra_struct_semi);
ConsumeToken();
continue;
}
-
+
// Set the default visibility to private.
if (Tok.is(tok::at)) { // parse objc-visibility-spec
ConsumeToken(); // eat the @ sign
@@ -875,18 +886,18 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
case tok::objc_package:
visibility = Tok.getObjCKeywordID();
ConsumeToken();
- continue;
+ continue;
default:
Diag(Tok, diag::err_objc_illegal_visibility_spec);
continue;
}
}
-
+
// Parse all the comma separated declarators.
DeclSpec DS;
FieldDeclarators.clear();
ParseStructDeclaration(DS, FieldDeclarators);
-
+
// Convert them all to fields.
for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) {
FieldDeclarator &FD = FieldDeclarators[i];
@@ -897,7 +908,7 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
FD.D, FD.BitfieldSize, visibility);
AllIvarDecls.push_back(Field);
}
-
+
if (Tok.is(tok::semi)) {
ConsumeToken();
} else {
@@ -920,9 +931,9 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
/// objc-protocol-forward-reference
///
/// objc-protocol-definition:
-/// @protocol identifier
-/// objc-protocol-refs[opt]
-/// objc-interface-decl-list
+/// @protocol identifier
+/// objc-protocol-refs[opt]
+/// objc-interface-decl-list
/// @end
///
/// objc-protocol-forward-reference:
@@ -936,7 +947,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
"ParseObjCAtProtocolDeclaration(): Expected @protocol");
ConsumeToken(); // the "protocol" identifier
-
+
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident); // missing protocol name.
return DeclPtrTy();
@@ -944,14 +955,14 @@ Parser::DeclPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
// Save the protocol name, then consume it.
IdentifierInfo *protocolName = Tok.getIdentifierInfo();
SourceLocation nameLoc = ConsumeToken();
-
+
if (Tok.is(tok::semi)) { // forward declaration of one protocol.
IdentifierLocPair ProtoInfo(protocolName, nameLoc);
ConsumeToken();
- return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1,
+ return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1,
attrList);
}
-
+
if (Tok.is(tok::comma)) { // list of forward declarations.
llvm::SmallVector<IdentifierLocPair, 8> ProtocolRefs;
ProtocolRefs.push_back(std::make_pair(protocolName, nameLoc));
@@ -967,28 +978,30 @@ Parser::DeclPtrTy Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
ProtocolRefs.push_back(IdentifierLocPair(Tok.getIdentifierInfo(),
Tok.getLocation()));
ConsumeToken(); // the identifier
-
+
if (Tok.isNot(tok::comma))
break;
}
// Consume the ';'.
if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@protocol"))
return DeclPtrTy();
-
+
return Actions.ActOnForwardProtocolDeclaration(AtLoc,
- &ProtocolRefs[0],
+ &ProtocolRefs[0],
ProtocolRefs.size(),
attrList);
}
-
+
// Last, and definitely not least, parse a protocol declaration.
- SourceLocation EndProtoLoc;
+ SourceLocation LAngleLoc, EndProtoLoc;
llvm::SmallVector<DeclPtrTy, 8> ProtocolRefs;
+ llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
if (Tok.is(tok::less) &&
- ParseObjCProtocolReferences(ProtocolRefs, false, EndProtoLoc))
+ ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false,
+ LAngleLoc, EndProtoLoc))
return DeclPtrTy();
-
+
DeclPtrTy ProtoType =
Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc,
ProtocolRefs.data(),
@@ -1013,7 +1026,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
"ParseObjCAtImplementationDeclaration(): Expected @implementation");
ConsumeToken(); // the "implementation" identifier
-
+
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident); // missing class or category name.
return DeclPtrTy();
@@ -1021,20 +1034,20 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
// We have a class or category name - consume it.
IdentifierInfo *nameId = Tok.getIdentifierInfo();
SourceLocation nameLoc = ConsumeToken(); // consume class or category name
-
- if (Tok.is(tok::l_paren)) {
+
+ if (Tok.is(tok::l_paren)) {
// we have a category implementation.
SourceLocation lparenLoc = ConsumeParen();
SourceLocation categoryLoc, rparenLoc;
IdentifierInfo *categoryId = 0;
-
+
if (Tok.is(tok::identifier)) {
categoryId = Tok.getIdentifierInfo();
categoryLoc = ConsumeToken();
} else {
Diag(Tok, diag::err_expected_ident); // missing category name.
return DeclPtrTy();
- }
+ }
if (Tok.isNot(tok::r_paren)) {
Diag(Tok, diag::err_expected_rparen);
SkipUntil(tok::r_paren, false); // don't stop at ';'
@@ -1042,7 +1055,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
}
rparenLoc = ConsumeParen();
DeclPtrTy ImplCatType = Actions.ActOnStartCategoryImplementation(
- atLoc, nameId, nameLoc, categoryId,
+ atLoc, nameId, nameLoc, categoryId,
categoryLoc);
ObjCImpDecl = ImplCatType;
return DeclPtrTy();
@@ -1063,11 +1076,11 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
DeclPtrTy ImplClsType = Actions.ActOnStartClassImplementation(
atLoc, nameId, nameLoc,
superClassId, superClassLoc);
-
+
if (Tok.is(tok::l_brace)) // we have ivars
ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/, atLoc);
ObjCImpDecl = ImplClsType;
-
+
return DeclPtrTy();
}
@@ -1131,7 +1144,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
Diag(Tok, diag::err_expected_ident);
return DeclPtrTy();
}
-
+
while (Tok.is(tok::identifier)) {
IdentifierInfo *propertyIvar = 0;
IdentifierInfo *propertyId = Tok.getIdentifierInfo();
@@ -1186,7 +1199,7 @@ Parser::DeclPtrTy Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
Diag(Tok, diag::err_expected_semi_after) << "@dynamic";
return DeclPtrTy();
}
-
+
/// objc-throw-statement:
/// throw expression[opt];
///
@@ -1288,7 +1301,7 @@ Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
DeclSpec DS;
ParseDeclarationSpecifiers(DS);
// For some odd reason, the name of the exception variable is
- // optional. As a result, we need to use "PrototypeContext", because
+ // optional. As a result, we need to use "PrototypeContext", because
// we must accept either 'declarator' or 'abstract-declarator' here.
Declarator ParmDecl(DS, Declarator::PrototypeContext);
ParseDeclarator(ParmDecl);
@@ -1298,9 +1311,9 @@ Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
FirstPart = Actions.ActOnParamDeclarator(CurScope, ParmDecl);
} else
ConsumeToken(); // consume '...'
-
+
SourceLocation RParenLoc;
-
+
if (Tok.is(tok::r_paren))
RParenLoc = ConsumeParen();
else // Skip over garbage, until we get to ')'. Eat the ')'.
@@ -1352,11 +1365,11 @@ Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
///
Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {
DeclPtrTy MDecl = ParseObjCMethodPrototype(ObjCImpDecl);
-
+
PrettyStackTraceActionsDecl CrashInfo(MDecl, Tok.getLocation(), Actions,
PP.getSourceManager(),
"parsing Objective-C method");
-
+
// parse optional ';'
if (Tok.is(tok::semi))
ConsumeToken();
@@ -1364,19 +1377,19 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {
// We should have an opening brace now.
if (Tok.isNot(tok::l_brace)) {
Diag(Tok, diag::err_expected_method_body);
-
+
// Skip over garbage, until we get to '{'. Don't eat the '{'.
SkipUntil(tok::l_brace, true, true);
-
+
// If we didn't find the '{', bail out.
if (Tok.isNot(tok::l_brace))
return DeclPtrTy();
}
SourceLocation BraceLoc = Tok.getLocation();
-
+
// Enter a scope for the method body.
ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope);
-
+
// Tell the actions module that we have entered a method definition with the
// specified Declarator for the method.
Actions.ActOnStartOfObjCMethodDef(CurScope, MDecl);
@@ -1390,7 +1403,7 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {
// TODO: Pass argument information.
Actions.ActOnFinishFunctionBody(MDecl, move(FnBody));
-
+
// Leave the function body scope.
BodyScope.Exit();
@@ -1439,7 +1452,7 @@ Parser::OwningExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
}
}
-/// objc-message-expr:
+/// objc-message-expr:
/// '[' objc-receiver objc-message-args ']'
///
/// objc-receiver:
@@ -1472,7 +1485,7 @@ Parser::OwningExprResult Parser::ParseObjCMessageExpression() {
/// ParseObjCMessageExpressionBody - Having parsed "'[' objc-receiver", parse
/// the rest of a message expression.
-///
+///
/// objc-message-args:
/// objc-selector
/// objc-keywordarg-list
@@ -1481,7 +1494,7 @@ Parser::OwningExprResult Parser::ParseObjCMessageExpression() {
/// objc-keywordarg
/// objc-keywordarg-list objc-keywordarg
///
-/// objc-keywordarg:
+/// objc-keywordarg:
/// selector-name[opt] ':' objc-keywordexpr
///
/// objc-keywordexpr:
@@ -1501,7 +1514,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc);
SourceLocation SelectorLoc = Loc;
-
+
llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
ExprVector KeyExprs(Actions);
@@ -1520,7 +1533,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
}
ConsumeToken(); // Eat the ':'.
- /// Parse the expression after ':'
+ /// Parse the expression after ':'
OwningExprResult Res(ParseAssignmentExpression());
if (Res.isInvalid()) {
// We must manually skip to a ']', otherwise the expression skipper will
@@ -1542,7 +1555,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
// Parse the, optional, argument list, comma separated.
while (Tok.is(tok::comma)) {
ConsumeToken(); // Eat the ','.
- /// Parse the expression after ','
+ /// Parse the expression after ','
OwningExprResult Res(ParseAssignmentExpression());
if (Res.isInvalid()) {
// We must manually skip to a ']', otherwise the expression skipper will
@@ -1584,7 +1597,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
// We've just parsed a keyword message.
if (ReceiverName)
return Owned(Actions.ActOnClassMessage(CurScope, ReceiverName, Sel,
- LBracLoc, NameLoc, SelectorLoc,
+ LBracLoc, NameLoc, SelectorLoc,
RBracLoc,
KeyExprs.take(), KeyExprs.size()));
return Owned(Actions.ActOnInstanceMessage(ReceiverExpr.release(), Sel,
@@ -1642,7 +1655,7 @@ Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
if (Ty.isInvalid())
return ExprError();
- return Owned(Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, LParenLoc,
+ return Owned(Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, LParenLoc,
Ty.get(), RParenLoc));
}
diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp
index 58c729aef29e..812d8e2af901 100644
--- a/lib/Parse/ParsePragma.cpp
+++ b/lib/Parse/ParsePragma.cpp
@@ -37,7 +37,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
IdentifierInfo *Name = 0;
Action::OwningExprResult Alignment(Actions);
SourceLocation LParenLoc = Tok.getLocation();
- PP.Lex(Tok);
+ PP.Lex(Tok);
if (Tok.is(tok::numeric_constant)) {
Alignment = Actions.ActOnNumericConstant(Tok);
if (Alignment.isInvalid())
@@ -57,12 +57,12 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
} else {
PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
return;
- }
+ }
PP.Lex(Tok);
-
+
if (Tok.is(tok::comma)) {
PP.Lex(Tok);
-
+
if (Tok.is(tok::numeric_constant)) {
Alignment = Actions.ActOnNumericConstant(Tok);
if (Alignment.isInvalid())
@@ -72,15 +72,15 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
} else if (Tok.is(tok::identifier)) {
Name = Tok.getIdentifierInfo();
PP.Lex(Tok);
-
+
if (Tok.is(tok::comma)) {
PP.Lex(Tok);
-
+
if (Tok.isNot(tok::numeric_constant)) {
PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
return;
}
-
+
Alignment = Actions.ActOnNumericConstant(Tok);
if (Alignment.isInvalid())
return;
@@ -115,7 +115,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) {
// FIXME: Should we be expanding macros here? My guess is no.
SourceLocation UnusedLoc = UnusedTok.getLocation();
-
+
// Lex the left '('.
Token Tok;
PP.Lex(Tok);
@@ -124,57 +124,39 @@ void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) {
return;
}
SourceLocation LParenLoc = Tok.getLocation();
-
+
// Lex the declaration reference(s).
- llvm::SmallVector<Action::ExprTy*, 5> Ex;
+ llvm::SmallVector<Token, 5> Identifiers;
SourceLocation RParenLoc;
bool LexID = true;
-
+
while (true) {
PP.Lex(Tok);
-
+
if (LexID) {
- if (Tok.is(tok::identifier)) {
- Action::OwningExprResult Name =
- Actions.ActOnIdentifierExpr(parser.CurScope, Tok.getLocation(),
- *Tok.getIdentifierInfo(), false);
-
- if (Name.isInvalid()) {
- if (!Ex.empty())
- Action::MultiExprArg Release(Actions, &Ex[0], Ex.size());
- return;
- }
-
- Ex.push_back(Name.release());
+ if (Tok.is(tok::identifier)) {
+ Identifiers.push_back(Tok);
LexID = false;
continue;
}
- // Illegal token! Release the parsed expressions (if any) and emit
- // a warning.
- if (!Ex.empty())
- Action::MultiExprArg Release(Actions, &Ex[0], Ex.size());
-
+ // Illegal token!
PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
return;
}
-
+
// We are execting a ')' or a ','.
if (Tok.is(tok::comma)) {
LexID = true;
continue;
}
-
+
if (Tok.is(tok::r_paren)) {
RParenLoc = Tok.getLocation();
break;
}
-
- // Illegal token! Release the parsed expressions (if any) and emit
- // a warning.
- if (!Ex.empty())
- Action::MultiExprArg Release(Actions, &Ex[0], Ex.size());
-
+
+ // Illegal token!
PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
return;
}
@@ -188,10 +170,11 @@ void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) {
// Verify that we have a location for the right parenthesis.
assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
- assert(!Ex.empty() && "Valid '#pragma unused' must have arguments");
+ assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
- // Perform the action to handle the pragma.
- Actions.ActOnPragmaUnused(&Ex[0], Ex.size(), UnusedLoc, LParenLoc, RParenLoc);
+ // Perform the action to handle the pragma.
+ Actions.ActOnPragmaUnused(Identifiers.data(), Identifiers.size(),
+ parser.CurScope, UnusedLoc, LParenLoc, RParenLoc);
}
// #pragma weak identifier
@@ -214,7 +197,7 @@ void PragmaWeakHandler::HandlePragma(Preprocessor &PP, Token &WeakTok) {
if (Tok.is(tok::equal)) {
PP.Lex(Tok);
if (Tok.isNot(tok::identifier)) {
- PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
+ PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
<< "weak";
return;
}
diff --git a/lib/Parse/ParsePragma.h b/lib/Parse/ParsePragma.h
index 39c86eea43b0..db385c6371e3 100644
--- a/lib/Parse/ParsePragma.h
+++ b/lib/Parse/ParsePragma.h
@@ -23,29 +23,29 @@ namespace clang {
class PragmaPackHandler : public PragmaHandler {
Action &Actions;
public:
- PragmaPackHandler(const IdentifierInfo *N, Action &A) : PragmaHandler(N),
+ PragmaPackHandler(const IdentifierInfo *N, Action &A) : PragmaHandler(N),
Actions(A) {}
-
- virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
+
+ virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
};
-
+
class PragmaUnusedHandler : public PragmaHandler {
Action &Actions;
Parser &parser;
public:
PragmaUnusedHandler(const IdentifierInfo *N, Action &A, Parser& p)
: PragmaHandler(N), Actions(A), parser(p) {}
-
- virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
-};
+
+ virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
+};
class PragmaWeakHandler : public PragmaHandler {
Action &Actions;
public:
PragmaWeakHandler(const IdentifierInfo *N, Action &A)
: PragmaHandler(N), Actions(A) {}
-
- virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
+
+ virtual void HandlePragma(Preprocessor &PP, Token &FirstToken);
};
} // end namespace clang
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 955f00d7a0b5..907ca802b4ae 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -71,8 +71,8 @@ using namespace clang;
///
/// [OBC] objc-throw-statement:
/// [OBC] '@' 'throw' expression ';'
-/// [OBC] '@' 'throw' ';'
-///
+/// [OBC] '@' 'throw' ';'
+///
Parser::OwningStmtResult
Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
const char *SemiError = 0;
@@ -90,6 +90,11 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
return ParseObjCAtStatement(AtLoc);
}
+ case tok::code_completion:
+ Actions.CodeCompleteOrdinaryName(CurScope);
+ ConsumeToken();
+ return ParseStatementOrDeclaration(OnlyStatement);
+
case tok::identifier:
if (NextToken().is(tok::colon)) { // C99 6.8.1: labeled-statement
// identifier ':' statement
@@ -108,7 +113,7 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
Diag(Tok, diag::err_expected_statement);
return StmtError();
}
-
+
// expression[opt] ';'
OwningExprResult Expr(ParseExpression());
if (Expr.isInvalid()) {
@@ -187,7 +192,7 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
// Skip until we see a } or ;, but don't eat it.
SkipUntil(tok::r_brace, true, true);
}
-
+
return move(Res);
}
@@ -233,7 +238,7 @@ Parser::OwningStmtResult Parser::ParseLabeledStatement() {
///
Parser::OwningStmtResult Parser::ParseCaseStatement() {
assert(Tok.is(tok::kw_case) && "Not a case stmt!");
-
+
// It is very very common for code to contain many case statements recursively
// nested, as in (but usually without indentation):
// case 1:
@@ -247,19 +252,24 @@ Parser::OwningStmtResult Parser::ParseCaseStatement() {
// flatten this recursion into an iterative loop. This is complex and gross,
// but all the grossness is constrained to ParseCaseStatement (and some
// wierdness in the actions), so this is just local grossness :).
-
+
// TopLevelCase - This is the highest level we have parsed. 'case 1' in the
// example above.
OwningStmtResult TopLevelCase(Actions, true);
-
+
// DeepestParsedCaseStmt - This is the deepest statement we have parsed, which
// gets updated each time a new case is parsed, and whose body is unset so
// far. When parsing 'case 4', this is the 'case 3' node.
StmtTy *DeepestParsedCaseStmt = 0;
-
+
// While we have case statements, eat and stack them.
do {
SourceLocation CaseLoc = ConsumeToken(); // eat the 'case'.
+
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteCase(CurScope);
+ ConsumeToken();
+ }
OwningExprResult LHS(ParseConstantExpression());
if (LHS.isInvalid()) {
@@ -288,11 +298,11 @@ Parser::OwningStmtResult Parser::ParseCaseStatement() {
}
SourceLocation ColonLoc = ConsumeToken();
-
+
OwningStmtResult Case =
Actions.ActOnCaseStmt(CaseLoc, move(LHS), DotDotDotLoc,
move(RHS), ColonLoc);
-
+
// If we had a sema error parsing this case, then just ignore it and
// continue parsing the sub-stmt.
if (Case.isInvalid()) {
@@ -309,15 +319,15 @@ Parser::OwningStmtResult Parser::ParseCaseStatement() {
Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, move(Case));
DeepestParsedCaseStmt = NextDeepest;
}
-
+
// Handle all case statements.
} while (Tok.is(tok::kw_case));
-
+
assert(!TopLevelCase.isInvalid() && "Should have parsed at least one case!");
-
+
// If we found a non-case statement, start by parsing it.
OwningStmtResult SubStmt(Actions);
-
+
if (Tok.isNot(tok::r_brace)) {
SubStmt = ParseStatement();
} else {
@@ -327,11 +337,11 @@ Parser::OwningStmtResult Parser::ParseCaseStatement() {
Diag(Tok, diag::err_label_end_of_compound_statement);
SubStmt = true;
}
-
+
// Broken sub-stmt shouldn't prevent forming the case statement properly.
if (SubStmt.isInvalid())
SubStmt = Actions.ActOnNullStmt(SourceLocation());
-
+
// Install the body into the most deeply-nested case.
Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, move(SubStmt));
@@ -415,10 +425,10 @@ Parser::OwningStmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
/// consume the '}' at the end of the block. It does not manipulate the scope
/// stack.
Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
- PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),
+ PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),
Tok.getLocation(),
"in compound statement ('{}')");
-
+
SourceLocation LBraceLoc = ConsumeBrace(); // eat the '{'.
// TODO: "__label__ X, Y, Z;" is the GNU "Local Label" extension. These are
@@ -496,12 +506,12 @@ bool Parser::ParseParenExprOrCondition(OwningExprResult &CondExp,
SourceLocation *RParenLocPtr) {
SourceLocation LParenLoc = ConsumeParen();
if (LParenLocPtr) *LParenLocPtr = LParenLoc;
-
+
if (getLang().CPlusPlus)
CondExp = ParseCXXCondition();
else
CondExp = ParseExpression();
-
+
// If the parser was confused by the condition and we don't have a ')', try to
// recover by skipping ahead to a semi and bailing out. If condexp is
// semantically invalid but we have well formed code, keep going.
@@ -512,7 +522,7 @@ bool Parser::ParseParenExprOrCondition(OwningExprResult &CondExp,
if (Tok.isNot(tok::r_paren))
return true;
}
-
+
// Otherwise the condition is valid or the rparen is present.
SourceLocation RPLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
if (RParenLocPtr) *RParenLocPtr = RPLoc;
@@ -559,7 +569,7 @@ Parser::OwningStmtResult Parser::ParseIfStatement() {
return StmtError();
FullExprArg FullCondExp(Actions.FullExpr(CondExp));
-
+
// C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
// there is no compound stmt. C90 does not have this clause. We only do this
// if the body isn't a compound statement to avoid push/pop in common cases.
@@ -578,7 +588,7 @@ Parser::OwningStmtResult Parser::ParseIfStatement() {
// would have to notify ParseStatement not to create a new scope. It's
// simpler to let it create a new scope.
//
- ParseScope InnerScope(this, Scope::DeclScope,
+ ParseScope InnerScope(this, Scope::DeclScope,
C99orCXX && Tok.isNot(tok::l_brace));
// Read the 'then' stmt.
@@ -619,14 +629,14 @@ Parser::OwningStmtResult Parser::ParseIfStatement() {
}
IfScope.Exit();
-
+
// If the condition was invalid, discard the if statement. We could recover
// better by replacing it with a valid expr, but don't do that yet.
if (CondExp.isInvalid())
return StmtError();
// If the then or else stmt is invalid and the other is valid (and present),
- // make turn the invalid one into a null stmt to avoid dropping the other
+ // make turn the invalid one into a null stmt to avoid dropping the other
// part. If both are invalid, return error.
if ((ThenStmt.isInvalid() && ElseStmt.isInvalid()) ||
(ThenStmt.isInvalid() && ElseStmt.get() == 0) ||
@@ -641,7 +651,7 @@ Parser::OwningStmtResult Parser::ParseIfStatement() {
if (ElseStmt.isInvalid())
ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
- return Actions.ActOnIfStmt(IfLoc, FullCondExp, move(ThenStmt),
+ return Actions.ActOnIfStmt(IfLoc, FullCondExp, move(ThenStmt),
ElseLoc, move(ElseStmt));
}
@@ -698,7 +708,7 @@ Parser::OwningStmtResult Parser::ParseSwitchStatement() {
// See comments in ParseIfStatement for why we create a scope for the
// condition and a new scope for substatement in C++.
//
- ParseScope InnerScope(this, Scope::DeclScope,
+ ParseScope InnerScope(this, Scope::DeclScope,
C99orCXX && Tok.isNot(tok::l_brace));
// Read the body statement.
@@ -763,7 +773,7 @@ Parser::OwningStmtResult Parser::ParseWhileStatement() {
return StmtError();
FullExprArg FullCond(Actions.FullExpr(Cond));
-
+
// C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
// there is no compound stmt. C90 does not have this clause. We only do this
// if the body isn't a compound statement to avoid push/pop in common cases.
@@ -775,7 +785,7 @@ Parser::OwningStmtResult Parser::ParseWhileStatement() {
// See comments in ParseIfStatement for why we create a scope for the
// condition and a new scope for substatement in C++.
//
- ParseScope InnerScope(this, Scope::DeclScope,
+ ParseScope InnerScope(this, Scope::DeclScope,
C99orCXX && Tok.isNot(tok::l_brace));
// Read the body statement.
@@ -818,7 +828,7 @@ Parser::OwningStmtResult Parser::ParseDoStatement() {
// which is entered and exited each time through the loop.
//
ParseScope InnerScope(this, Scope::DeclScope,
- (getLang().C99 || getLang().CPlusPlus) &&
+ (getLang().C99 || getLang().CPlusPlus) &&
Tok.isNot(tok::l_brace));
// Read the body statement.
@@ -847,7 +857,7 @@ Parser::OwningStmtResult Parser::ParseDoStatement() {
OwningExprResult Cond(Actions);
SourceLocation LPLoc, RPLoc;
ParseParenExprOrCondition(Cond, true, &LPLoc, &RPLoc);
-
+
DoScope.Exit();
if (Cond.isInvalid() || Body.isInvalid())
@@ -913,6 +923,11 @@ Parser::OwningStmtResult Parser::ParseForStatement() {
OwningStmtResult FirstPart(Actions);
OwningExprResult SecondPart(Actions), ThirdPart(Actions);
+ if (Tok.is(tok::code_completion)) {
+ Actions.CodeCompleteOrdinaryName(CurScope);
+ ConsumeToken();
+ }
+
// Parse the first part of the for specifier.
if (Tok.is(tok::semi)) { // for (;
// no first part, eat the ';'.
@@ -926,11 +941,11 @@ Parser::OwningStmtResult Parser::ParseForStatement() {
DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd,
false);
FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
-
+
if (Tok.is(tok::semi)) { // for (int x = 4;
ConsumeToken();
} else if ((ForEach = isTokIdentifier_in())) {
- // ObjC: for (id x in expr)
+ // ObjC: for (id x in expr)
ConsumeToken(); // consume 'in'
SecondPart = ParseExpression();
} else {
@@ -988,7 +1003,7 @@ Parser::OwningStmtResult Parser::ParseForStatement() {
// See comments in ParseIfStatement for why we create a scope for
// for-init-statement/condition and a new scope for substatement in C++.
//
- ParseScope InnerScope(this, Scope::DeclScope,
+ ParseScope InnerScope(this, Scope::DeclScope,
C99orCXXorObjC && Tok.isNot(tok::l_brace));
// Read the body statement.
@@ -1007,7 +1022,7 @@ Parser::OwningStmtResult Parser::ParseForStatement() {
return Actions.ActOnForStmt(ForLoc, LParenLoc, move(FirstPart),
move(SecondPart), move(ThirdPart),
RParenLoc, move(Body));
-
+
return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc,
move(FirstPart),
move(SecondPart),
@@ -1085,7 +1100,7 @@ Parser::OwningStmtResult Parser::ParseReturnStatement() {
return StmtError();
}
}
- return Actions.ActOnReturnStmt(ReturnLoc, Actions.FullExpr(R));
+ return Actions.ActOnReturnStmt(ReturnLoc, move(R));
}
/// FuzzyParseMicrosoftAsmStatement. When -fms-extensions is enabled, this
@@ -1096,7 +1111,7 @@ Parser::OwningStmtResult Parser::FuzzyParseMicrosoftAsmStatement() {
do {
ConsumeAnyToken();
} while (BraceCount > savedBraceCount && Tok.isNot(tok::eof));
- } else {
+ } else {
// From the MS website: If used without braces, the __asm keyword means
// that the rest of the line is an assembly-language statement.
SourceManager &SrcMgr = PP.getSourceManager();
@@ -1105,8 +1120,8 @@ Parser::OwningStmtResult Parser::FuzzyParseMicrosoftAsmStatement() {
do {
ConsumeAnyToken();
TokLoc = Tok.getLocation();
- } while ((SrcMgr.getInstantiationLineNumber(TokLoc) == LineNo) &&
- Tok.isNot(tok::r_brace) && Tok.isNot(tok::semi) &&
+ } while ((SrcMgr.getInstantiationLineNumber(TokLoc) == LineNo) &&
+ Tok.isNot(tok::r_brace) && Tok.isNot(tok::semi) &&
Tok.isNot(tok::eof));
}
return Actions.ActOnNullStmt(Tok.getLocation());
@@ -1196,7 +1211,7 @@ Parser::OwningStmtResult Parser::ParseAsmStatement(bool &msAsm) {
return StmtError();
assert(Names.size() == Constraints.size() &&
- Constraints.size() == Exprs.size()
+ Constraints.size() == Exprs.size()
&& "Input operand size mismatch!");
NumInputs = Names.size() - NumOutputs;
@@ -1247,22 +1262,22 @@ bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names,
// Only do anything if this operand is present.
if (Tok.isNot(tok::colon)) return false;
ConsumeToken();
-
+
// 'asm-operands' isn't present?
if (!isTokenStringLiteral() && Tok.isNot(tok::l_square))
return false;
-
- while (1) {
+
+ while (1) {
// Read the [id] if present.
if (Tok.is(tok::l_square)) {
SourceLocation Loc = ConsumeBracket();
-
+
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
SkipUntil(tok::r_paren);
return true;
}
-
+
IdentifierInfo *II = Tok.getIdentifierInfo();
ConsumeToken();
@@ -1308,7 +1323,7 @@ Parser::DeclPtrTy Parser::ParseFunctionStatementBody(DeclPtrTy Decl) {
PrettyStackTraceActionsDecl CrashInfo(Decl, LBraceLoc, Actions,
PP.getSourceManager(),
"parsing function body");
-
+
// Do not enter a scope for the brace, as the arguments are in the same scope
// (the function body) as the body itself. Instead, just read the statement
// list and put it into a CompoundStmt for safe keeping.
@@ -1316,7 +1331,7 @@ Parser::DeclPtrTy Parser::ParseFunctionStatementBody(DeclPtrTy Decl) {
// If the function body could not be parsed, make a bogus compoundstmt.
if (FnBody.isInvalid())
- FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
+ FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
MultiStmtArg(Actions), false);
return Actions.ActOnFinishFunctionBody(Decl, move(FnBody));
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 57a09fbc737f..8e63fb89db31 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -15,6 +15,7 @@
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
+#include "llvm/Support/Compiler.h"
using namespace clang;
/// \brief Parse a template declaration, explicit instantiation, or
@@ -24,11 +25,35 @@ Parser::ParseDeclarationStartingWithTemplate(unsigned Context,
SourceLocation &DeclEnd,
AccessSpecifier AS) {
if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less))
- return ParseExplicitInstantiation(ConsumeToken(), DeclEnd);
+ return ParseExplicitInstantiation(SourceLocation(), ConsumeToken(),
+ DeclEnd);
return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS);
}
+/// \brief RAII class that manages the template parameter depth.
+namespace {
+ class VISIBILITY_HIDDEN TemplateParameterDepthCounter {
+ unsigned &Depth;
+ unsigned AddedLevels;
+
+ public:
+ explicit TemplateParameterDepthCounter(unsigned &Depth)
+ : Depth(Depth), AddedLevels(0) { }
+
+ ~TemplateParameterDepthCounter() {
+ Depth -= AddedLevels;
+ }
+
+ void operator++() {
+ ++Depth;
+ ++AddedLevels;
+ }
+
+ operator unsigned() const { return Depth; }
+ };
+}
+
/// \brief Parse a template declaration or an explicit specialization.
///
/// Template declarations include one or more template parameter lists
@@ -48,9 +73,9 @@ Parser::DeclPtrTy
Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
SourceLocation &DeclEnd,
AccessSpecifier AS) {
- assert((Tok.is(tok::kw_export) || Tok.is(tok::kw_template)) &&
- "Token does not start a template declaration.");
-
+ assert((Tok.is(tok::kw_export) || Tok.is(tok::kw_template)) &&
+ "Token does not start a template declaration.");
+
// Enter template-parameter scope.
ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
@@ -75,8 +100,9 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
// defining A<T>::B receives just the inner template parameter list
// (and retrieves the outer template parameter list from its
// context).
- bool isSpecialiation = true;
+ bool isSpecialization = true;
TemplateParameterLists ParamLists;
+ TemplateParameterDepthCounter Depth(TemplateParameterDepth);
do {
// Consume the 'export', if any.
SourceLocation ExportLoc;
@@ -92,27 +118,35 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
Diag(Tok.getLocation(), diag::err_expected_template);
return DeclPtrTy();
}
-
+
// Parse the '<' template-parameter-list '>'
SourceLocation LAngleLoc, RAngleLoc;
TemplateParameterList TemplateParams;
- ParseTemplateParameters(ParamLists.size(), TemplateParams, LAngleLoc,
- RAngleLoc);
-
- if (!TemplateParams.empty())
- isSpecialiation = false;
+ if (ParseTemplateParameters(Depth, TemplateParams, LAngleLoc,
+ RAngleLoc)) {
+ // Skip until the semi-colon or a }.
+ SkipUntil(tok::r_brace, true, true);
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+ return DeclPtrTy();
+ }
ParamLists.push_back(
- Actions.ActOnTemplateParameterList(ParamLists.size(), ExportLoc,
- TemplateLoc, LAngleLoc,
+ Actions.ActOnTemplateParameterList(Depth, ExportLoc,
+ TemplateLoc, LAngleLoc,
TemplateParams.data(),
TemplateParams.size(), RAngleLoc));
+
+ if (!TemplateParams.empty()) {
+ isSpecialization = false;
+ ++Depth;
+ }
} while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
// Parse the actual template declaration.
- return ParseSingleDeclarationAfterTemplate(Context,
+ return ParseSingleDeclarationAfterTemplate(Context,
ParsedTemplateInfo(&ParamLists,
- isSpecialiation),
+ isSpecialization),
DeclEnd, AS);
}
@@ -136,7 +170,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
/// declaration. Will be AS_none for namespace-scope declarations.
///
/// \returns the new declaration.
-Parser::DeclPtrTy
+Parser::DeclPtrTy
Parser::ParseSingleDeclarationAfterTemplate(
unsigned Context,
const ParsedTemplateInfo &TemplateInfo,
@@ -145,9 +179,14 @@ Parser::ParseSingleDeclarationAfterTemplate(
assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
"Template information required");
+ if (Context == Declarator::MemberContext) {
+ // We are parsing a member template.
+ ParseCXXClassMemberDeclaration(AS, TemplateInfo);
+ return DeclPtrTy::make((void*)0);
+ }
+
// Parse the declaration specifiers.
DeclSpec DS;
- // FIXME: Pass TemplateLoc through for explicit template instantiations
ParseDeclarationSpecifiers(DS, TemplateInfo, AS);
if (Tok.is(tok::semi)) {
@@ -166,7 +205,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
ConsumeToken();
return DeclPtrTy();
}
-
+
// If we have a declaration or declarator list, handle it.
if (isDeclarationAfterDeclarator()) {
// Parse this declaration.
@@ -181,7 +220,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
}
// Eat the semi colon after the declaration.
- ExpectAndConsume(tok::semi, diag::err_expected_semi_declation);
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration);
return ThisDecl;
}
@@ -217,44 +256,46 @@ Parser::ParseSingleDeclarationAfterTemplate(
/// is the number of template headers directly enclosing this template header.
/// TemplateParams is the current list of template parameters we're building.
/// The template parameter we parse will be added to this list. LAngleLoc and
-/// RAngleLoc will receive the positions of the '<' and '>', respectively,
+/// RAngleLoc will receive the positions of the '<' and '>', respectively,
/// that enclose this template parameter list.
+///
+/// \returns true if an error occurred, false otherwise.
bool Parser::ParseTemplateParameters(unsigned Depth,
TemplateParameterList &TemplateParams,
SourceLocation &LAngleLoc,
SourceLocation &RAngleLoc) {
// Get the template parameter list.
- if(!Tok.is(tok::less)) {
+ if (!Tok.is(tok::less)) {
Diag(Tok.getLocation(), diag::err_expected_less_after) << "template";
- return false;
+ return true;
}
LAngleLoc = ConsumeToken();
-
+
// Try to parse the template parameter list.
if (Tok.is(tok::greater))
RAngleLoc = ConsumeToken();
- else if(ParseTemplateParameterList(Depth, TemplateParams)) {
- if(!Tok.is(tok::greater)) {
+ else if (ParseTemplateParameterList(Depth, TemplateParams)) {
+ if (!Tok.is(tok::greater)) {
Diag(Tok.getLocation(), diag::err_expected_greater);
- return false;
+ return true;
}
RAngleLoc = ConsumeToken();
}
- return true;
+ return false;
}
/// ParseTemplateParameterList - Parse a template parameter list. If
/// the parsing fails badly (i.e., closing bracket was left out), this
/// will try to put the token stream in a reasonable position (closing
-/// a statement, etc.) and return false.
+/// a statement, etc.) and return false.
///
/// template-parameter-list: [C++ temp]
/// template-parameter
/// template-parameter-list ',' template-parameter
-bool
+bool
Parser::ParseTemplateParameterList(unsigned Depth,
TemplateParameterList &TemplateParams) {
- while(1) {
+ while (1) {
if (DeclPtrTy TmpParam
= ParseTemplateParameter(Depth, TemplateParams.size())) {
TemplateParams.push_back(TmpParam);
@@ -263,11 +304,11 @@ Parser::ParseTemplateParameterList(unsigned Depth,
// a comma or closing brace.
SkipUntil(tok::comma, tok::greater, true, true);
}
-
+
// Did we find a comma or the end of the template parmeter list?
- if(Tok.is(tok::comma)) {
+ if (Tok.is(tok::comma)) {
ConsumeToken();
- } else if(Tok.is(tok::greater)) {
+ } else if (Tok.is(tok::greater)) {
// Don't consume this... that's done by template parser.
break;
} else {
@@ -297,16 +338,16 @@ Parser::ParseTemplateParameterList(unsigned Depth,
/// 'typename' identifier[opt] '=' type-id
/// 'template' ...[opt][C++0x] '<' template-parameter-list '>' 'class' identifier[opt]
/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
-Parser::DeclPtrTy
+Parser::DeclPtrTy
Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
- if(Tok.is(tok::kw_class) ||
- (Tok.is(tok::kw_typename) &&
- // FIXME: Next token has not been annotated!
- NextToken().isNot(tok::annot_typename))) {
+ if (Tok.is(tok::kw_class) ||
+ (Tok.is(tok::kw_typename) &&
+ // FIXME: Next token has not been annotated!
+ NextToken().isNot(tok::annot_typename))) {
return ParseTypeParameter(Depth, Position);
}
-
- if(Tok.is(tok::kw_template))
+
+ if (Tok.is(tok::kw_template))
return ParseTemplateTemplateParameter(Depth, Position);
// If it's none of the above, then it must be a parameter declaration.
@@ -326,7 +367,7 @@ Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
/// 'typename' identifier[opt] '=' type-id
Parser::DeclPtrTy Parser::ParseTypeParameter(unsigned Depth, unsigned Position){
assert((Tok.is(tok::kw_class) || Tok.is(tok::kw_typename)) &&
- "A type-parameter starts with 'class' or 'typename'");
+ "A type-parameter starts with 'class' or 'typename'");
// Consume the 'class' or 'typename' keyword.
bool TypenameKeyword = Tok.is(tok::kw_typename);
@@ -338,33 +379,33 @@ Parser::DeclPtrTy Parser::ParseTypeParameter(unsigned Depth, unsigned Position){
if (Tok.is(tok::ellipsis)) {
Ellipsis = true;
EllipsisLoc = ConsumeToken();
-
- if (!getLang().CPlusPlus0x)
+
+ if (!getLang().CPlusPlus0x)
Diag(EllipsisLoc, diag::err_variadic_templates);
}
-
+
// Grab the template parameter name (if given)
SourceLocation NameLoc;
IdentifierInfo* ParamName = 0;
- if(Tok.is(tok::identifier)) {
+ if (Tok.is(tok::identifier)) {
ParamName = Tok.getIdentifierInfo();
NameLoc = ConsumeToken();
- } else if(Tok.is(tok::equal) || Tok.is(tok::comma) ||
- Tok.is(tok::greater)) {
+ } else if (Tok.is(tok::equal) || Tok.is(tok::comma) ||
+ Tok.is(tok::greater)) {
// Unnamed template parameter. Don't have to do anything here, just
// don't consume this token.
} else {
Diag(Tok.getLocation(), diag::err_expected_ident);
return DeclPtrTy();
}
-
+
DeclPtrTy TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword,
Ellipsis, EllipsisLoc,
KeyLoc, ParamName, NameLoc,
Depth, Position);
// Grab a default type id (if given).
- if(Tok.is(tok::equal)) {
+ if (Tok.is(tok::equal)) {
SourceLocation EqualLoc = ConsumeToken();
SourceLocation DefaultLoc = Tok.getLocation();
TypeResult DefaultType = ParseTypeName();
@@ -372,12 +413,12 @@ Parser::DeclPtrTy Parser::ParseTypeParameter(unsigned Depth, unsigned Position){
Actions.ActOnTypeParameterDefault(TypeParam, EqualLoc, DefaultLoc,
DefaultType.get());
}
-
+
return TypeParam;
}
/// ParseTemplateTemplateParameter - Handle the parsing of template
-/// template parameters.
+/// template parameters.
///
/// type-parameter: [C++ temp.param]
/// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
@@ -388,20 +429,20 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
// Handle the template <...> part.
SourceLocation TemplateLoc = ConsumeToken();
- TemplateParameterList TemplateParams;
+ TemplateParameterList TemplateParams;
SourceLocation LAngleLoc, RAngleLoc;
{
ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
- if(!ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc,
- RAngleLoc)) {
+ if (ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc,
+ RAngleLoc)) {
return DeclPtrTy();
}
}
// Generate a meaningful error if the user forgot to put class before the
// identifier, comma, or greater.
- if(!Tok.is(tok::kw_class)) {
- Diag(Tok.getLocation(), diag::err_expected_class_before)
+ if (!Tok.is(tok::kw_class)) {
+ Diag(Tok.getLocation(), diag::err_expected_class_before)
<< PP.getSpelling(Tok);
return DeclPtrTy();
}
@@ -410,10 +451,10 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
// Get the identifier, if given.
SourceLocation NameLoc;
IdentifierInfo* ParamName = 0;
- if(Tok.is(tok::identifier)) {
+ if (Tok.is(tok::identifier)) {
ParamName = Tok.getIdentifierInfo();
NameLoc = ConsumeToken();
- } else if(Tok.is(tok::equal) || Tok.is(tok::comma) || Tok.is(tok::greater)) {
+ } else if (Tok.is(tok::equal) || Tok.is(tok::comma) || Tok.is(tok::greater)) {
// Unnamed template parameter. Don't have to do anything here, just
// don't consume this token.
} else {
@@ -421,10 +462,10 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
return DeclPtrTy();
}
- TemplateParamsTy *ParamList =
+ TemplateParamsTy *ParamList =
Actions.ActOnTemplateParameterList(Depth, SourceLocation(),
TemplateLoc, LAngleLoc,
- &TemplateParams[0],
+ &TemplateParams[0],
TemplateParams.size(),
RAngleLoc);
@@ -448,7 +489,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
}
/// ParseNonTypeTemplateParameter - Handle the parsing of non-type
-/// template parameters (e.g., in "template<int Size> class array;").
+/// template parameters (e.g., in "template<int Size> class array;").
///
/// template-parameter:
/// ...
@@ -460,7 +501,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
/// parameters.
/// FIXME: We need to make a ParseParameterDeclaration that works for
/// non-type template parameters and normal function parameters.
-Parser::DeclPtrTy
+Parser::DeclPtrTy
Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
SourceLocation StartLoc = Tok.getLocation();
@@ -483,7 +524,7 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
return DeclPtrTy();
}
- // Create the parameter.
+ // Create the parameter.
DeclPtrTy Param = Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl,
Depth, Position);
@@ -496,16 +537,16 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
// template-parameter, the first non-nested > is taken as the
// end of the template-parameter-list rather than a greater-than
// operator.
- GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
+ GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
OwningExprResult DefaultArg = ParseAssignmentExpression();
if (DefaultArg.isInvalid())
SkipUntil(tok::comma, tok::greater, true, true);
else if (Param)
- Actions.ActOnNonTypeTemplateParameterDefault(Param, EqualLoc,
+ Actions.ActOnNonTypeTemplateParameterDefault(Param, EqualLoc,
move(DefaultArg));
}
-
+
return Param;
}
@@ -527,9 +568,9 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
/// token that forms the template-id. Otherwise, we will leave the
/// last token in the stream (e.g., so that it can be replaced with an
/// annotation token).
-bool
+bool
Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template,
- SourceLocation TemplateNameLoc,
+ SourceLocation TemplateNameLoc,
const CXXScopeSpec *SS,
bool ConsumeLastToken,
SourceLocation &LAngleLoc,
@@ -587,7 +628,7 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template,
return false;
}
-
+
/// \brief Replace the tokens that form a simple-template-id with an
/// annotation token containing the complete template-id.
///
@@ -626,7 +667,7 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template,
/// formed, this function returns true.
///
bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
- const CXXScopeSpec *SS,
+ const CXXScopeSpec *SS,
SourceLocation TemplateKWLoc,
bool AllowTypeAnnotation) {
assert(getLang().CPlusPlus && "Can only annotate template-ids in C++");
@@ -643,12 +684,12 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
TemplateArgIsTypeList TemplateArgIsType;
TemplateArgLocationList TemplateArgLocations;
bool Invalid = ParseTemplateIdAfterTemplateName(Template, TemplateNameLoc,
- SS, false, LAngleLoc,
- TemplateArgs,
+ SS, false, LAngleLoc,
+ TemplateArgs,
TemplateArgIsType,
TemplateArgLocations,
RAngleLoc);
-
+
if (Invalid) {
// If we failed to parse the template ID but skipped ahead to a >, we're not
// going to be able to form a token annotation. Eat the '>' if present.
@@ -663,7 +704,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
// Build the annotation token.
if (TNK == TNK_Type_template && AllowTypeAnnotation) {
- Action::TypeResult Type
+ Action::TypeResult Type
= Actions.ActOnTemplateIdType(Template, TemplateNameLoc,
LAngleLoc, TemplateArgsPtr,
&TemplateArgLocations[0],
@@ -682,13 +723,13 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
Tok.setLocation(SS->getBeginLoc());
else if (TemplateKWLoc.isValid())
Tok.setLocation(TemplateKWLoc);
- else
+ else
Tok.setLocation(TemplateNameLoc);
} else {
// Build a template-id annotation token that can be processed
// later.
Tok.setKind(tok::annot_template_id);
- TemplateIdAnnotation *TemplateId
+ TemplateIdAnnotation *TemplateId
= TemplateIdAnnotation::Allocate(TemplateArgs.size());
TemplateId->TemplateNameLoc = TemplateNameLoc;
TemplateId->Name = Name;
@@ -731,21 +772,21 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
assert(Tok.is(tok::annot_template_id) && "Requires template-id tokens");
- TemplateIdAnnotation *TemplateId
+ TemplateIdAnnotation *TemplateId
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
assert((TemplateId->Kind == TNK_Type_template ||
TemplateId->Kind == TNK_Dependent_template_name) &&
"Only works for type and dependent templates");
-
- ASTTemplateArgsPtr TemplateArgsPtr(Actions,
+
+ ASTTemplateArgsPtr TemplateArgsPtr(Actions,
TemplateId->getTemplateArgs(),
TemplateId->getTemplateArgIsType(),
TemplateId->NumArgs);
- Action::TypeResult Type
+ Action::TypeResult Type
= Actions.ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
TemplateId->TemplateNameLoc,
- TemplateId->LAngleLoc,
+ TemplateId->LAngleLoc,
TemplateArgsPtr,
TemplateId->getTemplateArgLocations(),
TemplateId->RAngleLoc);
@@ -798,7 +839,7 @@ void *Parser::ParseTemplateArgument(bool &ArgIsType) {
/// template-argument-list: [C++ 14.2]
/// template-argument
/// template-argument-list ',' template-argument
-bool
+bool
Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
TemplateArgIsTypeList &TemplateArgIsType,
TemplateArgLocationList &TemplateArgLocations) {
@@ -826,15 +867,19 @@ Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs,
return Tok.isNot(tok::greater) && Tok.isNot(tok::greatergreater);
}
-/// \brief Parse a C++ explicit template instantiation
+/// \brief Parse a C++ explicit template instantiation
/// (C++ [temp.explicit]).
///
/// explicit-instantiation:
-/// 'template' declaration
-Parser::DeclPtrTy
-Parser::ParseExplicitInstantiation(SourceLocation TemplateLoc,
+/// 'extern' [opt] 'template' declaration
+///
+/// Note that the 'extern' is a GNU extension and C++0x feature.
+Parser::DeclPtrTy
+Parser::ParseExplicitInstantiation(SourceLocation ExternLoc,
+ SourceLocation TemplateLoc,
SourceLocation &DeclEnd) {
- return ParseSingleDeclarationAfterTemplate(Declarator::FileContext,
- ParsedTemplateInfo(TemplateLoc),
+ return ParseSingleDeclarationAfterTemplate(Declarator::FileContext,
+ ParsedTemplateInfo(ExternLoc,
+ TemplateLoc),
DeclEnd, AS_none);
}
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index 02687a216c7d..eb6e93540566 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -270,7 +270,7 @@ bool Parser::isCXXConditionDeclaration() {
return TPR == TPResult::True();
}
- /// \brief Determine whether the next set of tokens contains a type-id.
+ /// \brief Determine whether the next set of tokens contains a type-id.
///
/// The context parameter states what context we're parsing right
/// now, which affects how this routine copes with the token
@@ -288,7 +288,7 @@ bool Parser::isCXXConditionDeclaration() {
/// type-specifier-seq abstract-declarator[opt]
///
bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
-
+
isAmbiguous = false;
// C++ 8.2p2:
@@ -409,7 +409,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
while (1) {
if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier))
- TryAnnotateCXXScopeToken();
+ TryAnnotateCXXScopeToken(true);
if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) ||
(Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) {
@@ -427,8 +427,12 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
// direct-declarator:
// direct-abstract-declarator:
- if (Tok.is(tok::identifier) && mayHaveIdentifier) {
+ if ((Tok.is(tok::identifier) ||
+ (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) &&
+ mayHaveIdentifier) {
// declarator-id
+ if (Tok.is(tok::annot_cxxscope))
+ ConsumeToken();
ConsumeToken();
} else if (Tok.is(tok::l_paren)) {
ConsumeParen();
@@ -597,14 +601,14 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
if (NextToken().is(tok::kw_new) || // ::new
NextToken().is(tok::kw_delete)) // ::delete
return TPResult::False();
-
+
// Annotate typenames and C++ scope specifiers. If we get one, just
// recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
return isCXXDeclarationSpecifier();
// Otherwise, not a typename.
return TPResult::False();
-
+
// decl-specifier:
// storage-class-specifier
// type-specifier
@@ -650,7 +654,7 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
case tok::kw__Complex:
case tok::kw___attribute:
return TPResult::True();
-
+
// Microsoft
case tok::kw___declspec:
case tok::kw___cdecl:
@@ -681,6 +685,8 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
case tok::kw_char:
case tok::kw_wchar_t:
+ case tok::kw_char16_t:
+ case tok::kw_char32_t:
case tok::kw_bool:
case tok::kw_short:
case tok::kw_int:
@@ -752,7 +758,7 @@ Parser::TPResult Parser::TryParseDeclarationSpecifier() {
TryParseTypeofSpecifier();
else
ConsumeToken();
-
+
assert(Tok.is(tok::l_paren) && "Expected '('!");
return TPResult::Ambiguous();
}
@@ -874,7 +880,7 @@ Parser::TPResult Parser::TryParseParameterDeclarationClause() {
/// If TryParseFunctionDeclarator fully parsed the function declarator, it will
/// return TPResult::Ambiguous(), otherwise it will return either False() or
/// Error().
-///
+///
/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
/// exception-specification[opt]
///
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 9771cf7b8474..2f500a484da3 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -24,18 +24,18 @@ using namespace clang;
/// to the parser action.
class ActionCommentHandler : public CommentHandler {
Action &Actions;
-
+
public:
explicit ActionCommentHandler(Action &Actions) : Actions(Actions) { }
-
+
virtual void HandleComment(Preprocessor &PP, SourceRange Comment) {
Actions.ActOnComment(Comment);
}
};
Parser::Parser(Preprocessor &pp, Action &actions)
- : CrashInfo(*this), PP(pp), Actions(actions), Diags(PP.getDiagnostics()),
- GreaterThanIsOperator(true) {
+ : CrashInfo(*this), PP(pp), Actions(actions), Diags(PP.getDiagnostics()),
+ GreaterThanIsOperator(true), TemplateParameterDepth(0) {
Tok.setKind(tok::eof);
CurScope = 0;
NumCachedScopes = 0;
@@ -47,7 +47,7 @@ Parser::Parser(Preprocessor &pp, Action &actions)
PackHandler.reset(new
PragmaPackHandler(&PP.getIdentifierTable().get("pack"), actions));
PP.AddPragmaHandler(0, PackHandler.get());
-
+
UnusedHandler.reset(new
PragmaUnusedHandler(&PP.getIdentifierTable().get("unused"), actions,
*this));
@@ -56,9 +56,9 @@ Parser::Parser(Preprocessor &pp, Action &actions)
WeakHandler.reset(new
PragmaWeakHandler(&PP.getIdentifierTable().get("weak"), actions));
PP.AddPragmaHandler(0, WeakHandler.get());
-
+
CommentHandler.reset(new ActionCommentHandler(actions));
- PP.AddCommentHandler(CommentHandler.get());
+ PP.AddCommentHandler(CommentHandler.get());
}
/// If a crash happens while the parser is active, print out a line indicating
@@ -69,12 +69,12 @@ void PrettyStackTraceParserEntry::print(llvm::raw_ostream &OS) const {
OS << "<eof> parser at end of file\n";
return;
}
-
+
if (Tok.getLocation().isInvalid()) {
OS << "<unknown> parser at unknown location\n";
return;
}
-
+
const Preprocessor &PP = P.getPreprocessor();
Tok.getLocation().print(OS, PP.getSourceManager());
OS << ": current parser token '" << PP.getSpelling(Tok) << "'\n";
@@ -104,8 +104,8 @@ void Parser::SuggestParentheses(SourceLocation Loc, unsigned DK,
Diag(Loc, DK);
return;
}
-
- Diag(Loc, DK)
+
+ Diag(Loc, DK)
<< CodeModificationHint::CreateInsertion(ParenRange.getBegin(), "(")
<< CodeModificationHint::CreateInsertion(EndLoc, ")");
}
@@ -152,10 +152,10 @@ bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID,
const char *Spelling = 0;
SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation);
- if (EndLoc.isValid() &&
+ if (EndLoc.isValid() &&
(Spelling = tok::getTokenSimpleSpelling(ExpectedTok))) {
// Show what code to insert to fix this problem.
- Diag(EndLoc, DiagID)
+ Diag(EndLoc, DiagID)
<< Msg
<< CodeModificationHint::CreateInsertion(EndLoc, Spelling);
} else
@@ -365,7 +365,7 @@ void Parser::ParseTranslationUnit() {
DeclGroupPtrTy Res;
while (!ParseTopLevelDecl(Res))
/*parse them all*/;
-
+
ExitScope();
assert(CurScope == 0 && "Scope imbalance!");
}
@@ -375,7 +375,7 @@ void Parser::ParseTranslationUnit() {
/// external-declaration: [C99 6.9], declaration: [C++ dcl.dcl]
/// function-definition
/// declaration
-/// [EXT] ';'
+/// [C++0x] empty-declaration
/// [GNU] asm-definition
/// [GNU] __extension__ external-declaration
/// [OBJC] objc-class-definition
@@ -388,12 +388,18 @@ void Parser::ParseTranslationUnit() {
/// [GNU] asm-definition:
/// simple-asm-expr ';'
///
+/// [C++0x] empty-declaration:
+/// ';'
+///
+/// [C++0x/GNU] 'extern' 'template' declaration
Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration() {
DeclPtrTy SingleDecl;
switch (Tok.getKind()) {
case tok::semi:
- Diag(Tok, diag::ext_top_level_semi)
- << CodeModificationHint::CreateRemoval(SourceRange(Tok.getLocation()));
+ if (!getLang().CPlusPlus0x)
+ Diag(Tok, diag::ext_top_level_semi)
+ << CodeModificationHint::CreateRemoval(SourceRange(Tok.getLocation()));
+
ConsumeToken();
// TODO: Invoke action for top-level semicolon.
return DeclGroupPtrTy();
@@ -436,6 +442,10 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration() {
}
SingleDecl = ParseObjCMethodDefinition();
break;
+ case tok::code_completion:
+ Actions.CodeCompleteOrdinaryName(CurScope);
+ ConsumeToken();
+ return ParseExternalDeclaration();
case tok::kw_using:
case tok::kw_namespace:
case tok::kw_typedef:
@@ -447,11 +457,25 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration() {
SourceLocation DeclEnd;
return ParseDeclaration(Declarator::FileContext, DeclEnd);
}
+ case tok::kw_extern:
+ if (getLang().CPlusPlus && NextToken().is(tok::kw_template)) {
+ // Extern templates
+ SourceLocation ExternLoc = ConsumeToken();
+ SourceLocation TemplateLoc = ConsumeToken();
+ SourceLocation DeclEnd;
+ return Actions.ConvertDeclToDeclGroup(
+ ParseExplicitInstantiation(ExternLoc, TemplateLoc, DeclEnd));
+ }
+
+ // FIXME: Detect C++ linkage specifications here?
+
+ // Fall through to handle other declarations or function definitions.
+
default:
// We can't tell whether this is a function-definition or declaration yet.
return ParseDeclarationOrFunctionDefinition();
}
-
+
// This routine returns a DeclGroup, if the thing we parsed only contains a
// single decl, convert it now.
return Actions.ConvertDeclToDeclGroup(SingleDecl);
@@ -473,7 +497,7 @@ bool Parser::isDeclarationAfterDeclarator() {
/// declarator, indicates the start of a function definition.
bool Parser::isStartOfFunctionDefinition() {
return Tok.is(tok::l_brace) || // int X() {}
- (!getLang().CPlusPlus &&
+ (!getLang().CPlusPlus &&
isDeclarationSpecifier()) || // int X(f) int f; {}
(getLang().CPlusPlus &&
(Tok.is(tok::colon) || // X() : Base() {} (used for ctors)
@@ -484,7 +508,7 @@ bool Parser::isStartOfFunctionDefinition() {
/// a declaration. We can't tell which we have until we read up to the
/// compound-statement in function-definition. TemplateParams, if
/// non-NULL, provides the template parameters when we're parsing a
-/// C++ template-declaration.
+/// C++ template-declaration.
///
/// function-definition: [C99 6.9.1]
/// decl-specs declarator declaration-list[opt] compound-statement
@@ -515,16 +539,17 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
// attributes here, no types, etc.
if (getLang().ObjC2 && Tok.is(tok::at)) {
SourceLocation AtLoc = ConsumeToken(); // the "@"
- if (!Tok.isObjCAtKeyword(tok::objc_interface) &&
+ if (!Tok.isObjCAtKeyword(tok::objc_interface) &&
!Tok.isObjCAtKeyword(tok::objc_protocol)) {
Diag(Tok, diag::err_objc_unexpected_attr);
SkipUntil(tok::semi); // FIXME: better skip?
return DeclGroupPtrTy();
}
const char *PrevSpec = 0;
- if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec))
- Diag(AtLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
-
+ unsigned DiagID;
+ if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID))
+ Diag(AtLoc, DiagID) << PrevSpec;
+
DeclPtrTy TheDecl;
if (Tok.isObjCAtKeyword(tok::objc_protocol))
TheDecl = ParseObjCAtProtocolDeclaration(AtLoc, DS.getAttributes());
@@ -561,10 +586,10 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
DeclGroupPtrTy DG =
ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
// Eat the semi colon after the declaration.
- ExpectAndConsume(tok::semi, diag::err_expected_semi_declation);
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration);
return DG;
}
-
+
if (DeclaratorInfo.isFunctionDeclarator() &&
isStartOfFunctionDefinition()) {
if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
@@ -584,7 +609,7 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) {
DeclPtrTy TheDecl = ParseFunctionDefinition(DeclaratorInfo);
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
-
+
if (DeclaratorInfo.isFunctionDeclarator())
Diag(Tok, diag::err_expected_fn_body);
else
@@ -619,9 +644,10 @@ Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D,
// declaration-specifiers are completely optional in the grammar.
if (getLang().ImplicitInt && D.getDeclSpec().isEmpty()) {
const char *PrevSpec;
+ unsigned DiagID;
D.getMutableDeclSpec().SetTypeSpecType(DeclSpec::TST_int,
D.getIdentifierLoc(),
- PrevSpec);
+ PrevSpec, DiagID);
D.SetRangeBegin(D.getDeclSpec().getSourceRange().getBegin());
}
@@ -650,7 +676,7 @@ Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D,
// Tell the actions module that we have entered a function definition with the
// specified Declarator for the function.
- DeclPtrTy Res = TemplateInfo.TemplateParams?
+ DeclPtrTy Res = TemplateInfo.TemplateParams?
Actions.ActOnStartOfFunctionTemplateDef(CurScope,
Action::MultiTemplateParamsArg(Actions,
TemplateInfo.TemplateParams->data(),
@@ -665,6 +691,8 @@ Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D,
// ctor-initializer.
if (Tok.is(tok::colon))
ParseConstructorInitializer(Res);
+ else
+ Actions.ActOnDefaultCtorInitializers(Res);
return ParseFunctionStatementBody(Res);
}
@@ -858,24 +886,25 @@ Parser::OwningExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) {
///
/// This returns true if the token was annotated or an unrecoverable error
/// occurs.
-///
+///
/// Note that this routine emits an error if you call it with ::new or ::delete
/// as the current tokens, so only call it in contexts where these are invalid.
-bool Parser::TryAnnotateTypeOrScopeToken() {
- assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon)
+bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
+ assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon)
|| Tok.is(tok::kw_typename)) &&
"Cannot be a type or scope token!");
-
+
if (Tok.is(tok::kw_typename)) {
// Parse a C++ typename-specifier, e.g., "typename T::type".
//
// typename-specifier:
// 'typename' '::' [opt] nested-name-specifier identifier
- // 'typename' '::' [opt] nested-name-specifier template [opt]
+ // 'typename' '::' [opt] nested-name-specifier template [opt]
// simple-template-id
SourceLocation TypenameLoc = ConsumeToken();
CXXScopeSpec SS;
- bool HadNestedNameSpecifier = ParseOptionalCXXScopeSpecifier(SS);
+ bool HadNestedNameSpecifier
+ = ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
if (!HadNestedNameSpecifier) {
Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename);
return false;
@@ -884,10 +913,10 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
TypeResult Ty;
if (Tok.is(tok::identifier)) {
// FIXME: check whether the next token is '<', first!
- Ty = Actions.ActOnTypenameType(TypenameLoc, SS, *Tok.getIdentifierInfo(),
+ Ty = Actions.ActOnTypenameType(TypenameLoc, SS, *Tok.getIdentifierInfo(),
Tok.getLocation());
} else if (Tok.is(tok::annot_template_id)) {
- TemplateIdAnnotation *TemplateId
+ TemplateIdAnnotation *TemplateId
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
if (TemplateId->Kind == TNK_Function_template) {
Diag(Tok, diag::err_typename_refers_to_non_type_template)
@@ -896,7 +925,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
}
AnnotateTemplateIdTokenAsType(0);
- assert(Tok.is(tok::annot_typename) &&
+ assert(Tok.is(tok::annot_typename) &&
"AnnotateTemplateIdTokenAsType isn't working properly");
if (Tok.getAnnotationValue())
Ty = Actions.ActOnTypenameType(TypenameLoc, SS, SourceLocation(),
@@ -919,11 +948,11 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
CXXScopeSpec SS;
if (getLang().CPlusPlus)
- ParseOptionalCXXScopeSpecifier(SS);
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext);
if (Tok.is(tok::identifier)) {
// Determine whether the identifier is a type name.
- if (TypeTy *Ty = Actions.getTypeName(*Tok.getIdentifierInfo(),
+ if (TypeTy *Ty = Actions.getTypeName(*Tok.getIdentifierInfo(),
Tok.getLocation(), CurScope, &SS)) {
// This is a typename. Replace the current token in-place with an
// annotation type token.
@@ -932,26 +961,28 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
Tok.setAnnotationEndLoc(Tok.getLocation());
if (SS.isNotEmpty()) // it was a C++ qualified type name.
Tok.setLocation(SS.getBeginLoc());
-
+
// In case the tokens were cached, have Preprocessor replace
// them with the annotation token.
PP.AnnotateCachedTokens(Tok);
return true;
- }
+ }
if (!getLang().CPlusPlus) {
// If we're in C, we can't have :: tokens at all (the lexer won't return
// them). If the identifier is not a type, then it can't be scope either,
- // just early exit.
+ // just early exit.
return false;
}
-
+
// If this is a template-id, annotate with a template-id or type token.
if (NextToken().is(tok::less)) {
TemplateTy Template;
- if (TemplateNameKind TNK
- = Actions.isTemplateName(*Tok.getIdentifierInfo(),
- CurScope, Template, &SS))
+ if (TemplateNameKind TNK
+ = Actions.isTemplateName(CurScope, *Tok.getIdentifierInfo(),
+ Tok.getLocation(), &SS,
+ /*ObjectType=*/0, EnteringContext,
+ Template))
if (AnnotateTemplateIdToken(Template, TNK, &SS)) {
// If an unrecoverable error occurred, we need to return true here,
// because the token stream is in a damaged state. We may not return
@@ -964,10 +995,10 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
// template-id, is not part of the annotation. Fall through to
// push that token back into the stream and complete the C++ scope
// specifier annotation.
- }
+ }
if (Tok.is(tok::annot_template_id)) {
- TemplateIdAnnotation *TemplateId
+ TemplateIdAnnotation *TemplateId
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
if (TemplateId->Kind == TNK_Type_template) {
// A template-id that refers to a type was parsed into a
@@ -981,7 +1012,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
if (SS.isEmpty())
return Tok.isNot(tok::identifier) && Tok.isNot(tok::coloncolon);
-
+
// A C++ scope specifier that isn't followed by a typename.
// Push the current token back into the token stream (or revert it if it is
// cached) and use an annotation scope token for current token.
@@ -1003,17 +1034,17 @@ bool Parser::TryAnnotateTypeOrScopeToken() {
/// annotates C++ scope specifiers and template-ids. This returns
/// true if the token was annotated or there was an error that could not be
/// recovered from.
-///
+///
/// Note that this routine emits an error if you call it with ::new or ::delete
/// as the current tokens, so only call it in contexts where these are invalid.
-bool Parser::TryAnnotateCXXScopeToken() {
+bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
assert(getLang().CPlusPlus &&
"Call sites of this function should be guarded by checking for C++");
assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) &&
"Cannot be a type or scope token!");
CXXScopeSpec SS;
- if (!ParseOptionalCXXScopeSpecifier(SS))
+ if (!ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext))
return Tok.is(tok::annot_template_id);
// Push the current token back into the token stream (or revert it if it is