summaryrefslogtreecommitdiff
path: root/lib/Parse/ParseDeclCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse/ParseDeclCXX.cpp')
-rw-r--r--lib/Parse/ParseDeclCXX.cpp200
1 files changed, 125 insertions, 75 deletions
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 9ba44d07aba86..f8359f1e87d8e 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -24,7 +24,6 @@
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
-#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/SmallString.h"
using namespace clang;
@@ -33,24 +32,25 @@ using namespace clang;
/// may either be a top level namespace or a block-level namespace alias. If
/// there was an inline keyword, it has already been parsed.
///
-/// namespace-definition: [C++ 7.3: basic.namespace]
+/// namespace-definition: [C++: namespace.def]
/// named-namespace-definition
/// unnamed-namespace-definition
+/// nested-namespace-definition
+///
+/// named-namespace-definition:
+/// 'inline'[opt] 'namespace' attributes[opt] identifier '{'
+/// namespace-body '}'
///
/// unnamed-namespace-definition:
/// 'inline'[opt] 'namespace' attributes[opt] '{' namespace-body '}'
///
-/// named-namespace-definition:
-/// original-namespace-definition
-/// extension-namespace-definition
-///
-/// original-namespace-definition:
-/// 'inline'[opt] 'namespace' identifier attributes[opt]
-/// '{' namespace-body '}'
+/// nested-namespace-definition:
+/// 'namespace' enclosing-namespace-specifier '::' 'inline'[opt]
+/// identifier '{' namespace-body '}'
///
-/// extension-namespace-definition:
-/// 'inline'[opt] 'namespace' original-namespace-name
-/// '{' namespace-body '}'
+/// enclosing-namespace-specifier:
+/// identifier
+/// enclosing-namespace-specifier '::' 'inline'[opt] identifier
///
/// namespace-alias-definition: [C++ 7.3.2: namespace.alias]
/// 'namespace' identifier '=' qualified-namespace-specifier ';'
@@ -70,9 +70,8 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
SourceLocation IdentLoc;
IdentifierInfo *Ident = nullptr;
- std::vector<SourceLocation> ExtraIdentLoc;
- std::vector<IdentifierInfo*> ExtraIdent;
- std::vector<SourceLocation> ExtraNamespaceLoc;
+ InnerNamespaceInfoList ExtraNSs;
+ SourceLocation FirstNestedInlineLoc;
ParsedAttributesWithRange attrs(AttrFactory);
SourceLocation attrLoc;
@@ -88,15 +87,29 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
if (Tok.is(tok::identifier)) {
Ident = Tok.getIdentifierInfo();
IdentLoc = ConsumeToken(); // eat the identifier.
- while (Tok.is(tok::coloncolon) && NextToken().is(tok::identifier)) {
- ExtraNamespaceLoc.push_back(ConsumeToken());
- ExtraIdent.push_back(Tok.getIdentifierInfo());
- ExtraIdentLoc.push_back(ConsumeToken());
+ while (Tok.is(tok::coloncolon) &&
+ (NextToken().is(tok::identifier) ||
+ (NextToken().is(tok::kw_inline) &&
+ GetLookAheadToken(2).is(tok::identifier)))) {
+
+ InnerNamespaceInfo Info;
+ Info.NamespaceLoc = ConsumeToken();
+
+ if (Tok.is(tok::kw_inline)) {
+ Info.InlineLoc = ConsumeToken();
+ if (FirstNestedInlineLoc.isInvalid())
+ FirstNestedInlineLoc = Info.InlineLoc;
+ }
+
+ Info.Ident = Tok.getIdentifierInfo();
+ Info.IdentLoc = ConsumeToken();
+
+ ExtraNSs.push_back(Info);
}
}
// A nested namespace definition cannot have attributes.
- if (!ExtraNamespaceLoc.empty() && attrLoc.isValid())
+ if (!ExtraNSs.empty() && attrLoc.isValid())
Diag(attrLoc, diag::err_unexpected_nested_namespace_attribute);
// Read label attributes, if present.
@@ -138,13 +151,21 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
return nullptr;
}
- if (ExtraIdent.empty()) {
+ if (ExtraNSs.empty()) {
// Normal namespace definition, not a nested-namespace-definition.
} else if (InlineLoc.isValid()) {
Diag(InlineLoc, diag::err_inline_nested_namespace_definition);
+ } else if (getLangOpts().CPlusPlus2a) {
+ Diag(ExtraNSs[0].NamespaceLoc,
+ diag::warn_cxx14_compat_nested_namespace_definition);
+ if (FirstNestedInlineLoc.isValid())
+ Diag(FirstNestedInlineLoc,
+ diag::warn_cxx17_compat_inline_nested_namespace_definition);
} else if (getLangOpts().CPlusPlus17) {
- Diag(ExtraNamespaceLoc[0],
+ Diag(ExtraNSs[0].NamespaceLoc,
diag::warn_cxx14_compat_nested_namespace_definition);
+ if (FirstNestedInlineLoc.isValid())
+ Diag(FirstNestedInlineLoc, diag::ext_inline_nested_namespace_definition);
} else {
TentativeParsingAction TPA(*this);
SkipUntil(tok::r_brace, StopBeforeMatch);
@@ -152,26 +173,34 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
TPA.Revert();
if (!rBraceToken.is(tok::r_brace)) {
- Diag(ExtraNamespaceLoc[0], diag::ext_nested_namespace_definition)
- << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back());
+ Diag(ExtraNSs[0].NamespaceLoc, diag::ext_nested_namespace_definition)
+ << SourceRange(ExtraNSs.front().NamespaceLoc,
+ ExtraNSs.back().IdentLoc);
} else {
std::string NamespaceFix;
- for (std::vector<IdentifierInfo*>::iterator I = ExtraIdent.begin(),
- E = ExtraIdent.end(); I != E; ++I) {
- NamespaceFix += " { namespace ";
- NamespaceFix += (*I)->getName();
+ for (const auto &ExtraNS : ExtraNSs) {
+ NamespaceFix += " { ";
+ if (ExtraNS.InlineLoc.isValid())
+ NamespaceFix += "inline ";
+ NamespaceFix += "namespace ";
+ NamespaceFix += ExtraNS.Ident->getName();
}
std::string RBraces;
- for (unsigned i = 0, e = ExtraIdent.size(); i != e; ++i)
+ for (unsigned i = 0, e = ExtraNSs.size(); i != e; ++i)
RBraces += "} ";
- Diag(ExtraNamespaceLoc[0], diag::ext_nested_namespace_definition)
- << FixItHint::CreateReplacement(SourceRange(ExtraNamespaceLoc.front(),
- ExtraIdentLoc.back()),
- NamespaceFix)
+ Diag(ExtraNSs[0].NamespaceLoc, diag::ext_nested_namespace_definition)
+ << FixItHint::CreateReplacement(
+ SourceRange(ExtraNSs.front().NamespaceLoc,
+ ExtraNSs.back().IdentLoc),
+ NamespaceFix)
<< FixItHint::CreateInsertion(rBraceToken.getLocation(), RBraces);
}
+
+ // Warn about nested inline namespaces.
+ if (FirstNestedInlineLoc.isValid())
+ Diag(FirstNestedInlineLoc, diag::ext_inline_nested_namespace_definition);
}
// If we're still good, complain about inline namespaces in non-C++0x now.
@@ -192,8 +221,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
// Parse the contents of the namespace. This includes parsing recovery on
// any improperly nested namespaces.
- ParseInnerNamespace(ExtraIdentLoc, ExtraIdent, ExtraNamespaceLoc, 0,
- InlineLoc, attrs, T);
+ ParseInnerNamespace(ExtraNSs, 0, InlineLoc, attrs, T);
// Leave the namespace scope.
NamespaceScope.Exit();
@@ -206,13 +234,11 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,
}
/// ParseInnerNamespace - Parse the contents of a namespace.
-void Parser::ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc,
- std::vector<IdentifierInfo *> &Ident,
- std::vector<SourceLocation> &NamespaceLoc,
+void Parser::ParseInnerNamespace(const InnerNamespaceInfoList &InnerNSs,
unsigned int index, SourceLocation &InlineLoc,
ParsedAttributes &attrs,
BalancedDelimiterTracker &Tracker) {
- if (index == Ident.size()) {
+ if (index == InnerNSs.size()) {
while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
Tok.isNot(tok::eof)) {
ParsedAttributesWithRange attrs(AttrFactory);
@@ -233,14 +259,13 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc,
ParseScope NamespaceScope(this, Scope::DeclScope);
UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr;
Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(
- getCurScope(), SourceLocation(), NamespaceLoc[index], IdentLoc[index],
- Ident[index], Tracker.getOpenLocation(), attrs,
- ImplicitUsingDirectiveDecl);
+ getCurScope(), InnerNSs[index].InlineLoc, InnerNSs[index].NamespaceLoc,
+ InnerNSs[index].IdentLoc, InnerNSs[index].Ident,
+ Tracker.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl);
assert(!ImplicitUsingDirectiveDecl &&
"nested namespace definition cannot define anonymous namespace");
- ParseInnerNamespace(IdentLoc, Ident, NamespaceLoc, ++index, InlineLoc,
- attrs, Tracker);
+ ParseInnerNamespace(InnerNSs, ++index, InlineLoc, attrs, Tracker);
NamespaceScope.Exit();
Actions.ActOnFinishNamespaceDef(NamespcDecl, Tracker.getCloseLocation());
@@ -365,7 +390,7 @@ Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) {
case tok::r_brace:
if (!NestedModules)
break;
- // Fall through.
+ LLVM_FALLTHROUGH;
default:
ParsedAttributesWithRange attrs(AttrFactory);
MaybeParseCXX11Attributes(attrs);
@@ -2321,32 +2346,22 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(
if (D.isFunctionDeclarator()) {
auto &Function = D.getFunctionTypeInfo();
if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {
- auto DeclSpecCheck = [&] (DeclSpec::TQ TypeQual,
- const char *FixItName,
- SourceLocation SpecLoc,
- unsigned* QualifierLoc) {
+ auto DeclSpecCheck = [&](DeclSpec::TQ TypeQual, StringRef FixItName,
+ SourceLocation SpecLoc) {
FixItHint Insertion;
- if (DS.getTypeQualifiers() & TypeQual) {
- if (!(Function.TypeQuals & TypeQual)) {
- std::string Name(FixItName);
- Name += " ";
- Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name);
- Function.TypeQuals |= TypeQual;
- *QualifierLoc = SpecLoc.getRawEncoding();
- }
- Diag(SpecLoc, diag::err_declspec_after_virtspec)
+ auto &MQ = Function.getOrCreateMethodQualifiers();
+ if (!(MQ.getTypeQualifiers() & TypeQual)) {
+ std::string Name(FixItName.data());
+ Name += " ";
+ Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name);
+ MQ.SetTypeQual(TypeQual, SpecLoc);
+ }
+ Diag(SpecLoc, diag::err_declspec_after_virtspec)
<< FixItName
<< VirtSpecifiers::getSpecifierName(VS.getLastSpecifier())
- << FixItHint::CreateRemoval(SpecLoc)
- << Insertion;
- }
+ << FixItHint::CreateRemoval(SpecLoc) << Insertion;
};
- DeclSpecCheck(DeclSpec::TQ_const, "const", DS.getConstSpecLoc(),
- &Function.ConstQualifierLoc);
- DeclSpecCheck(DeclSpec::TQ_volatile, "volatile", DS.getVolatileSpecLoc(),
- &Function.VolatileQualifierLoc);
- DeclSpecCheck(DeclSpec::TQ_restrict, "restrict", DS.getRestrictSpecLoc(),
- &Function.RestrictQualifierLoc);
+ DS.forEachQualifier(DeclSpecCheck);
}
// Parse ref-qualifiers.
@@ -2410,7 +2425,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
const ParsedTemplateInfo &TemplateInfo,
ParsingDeclRAIIObject *TemplateDiags) {
if (Tok.is(tok::at)) {
- if (getLangOpts().ObjC1 && NextToken().isObjCAtKeyword(tok::objc_defs))
+ if (getLangOpts().ObjC && NextToken().isObjCAtKeyword(tok::objc_defs))
Diag(Tok, diag::err_at_defs_cxx);
else
Diag(Tok, diag::err_at_in_class);
@@ -3449,6 +3464,7 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
+ // FIXME: Add support for signature help inside initializer lists.
ExprResult InitList = ParseBraceInitializer();
if (InitList.isInvalid())
return true;
@@ -3466,7 +3482,20 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
// Parse the optional expression-list.
ExprVector ArgExprs;
CommaLocsTy CommaLocs;
- if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) {
+ if (Tok.isNot(tok::r_paren) &&
+ ParseExpressionList(ArgExprs, CommaLocs, [&] {
+ QualType PreferredType = Actions.ProduceCtorInitMemberSignatureHelp(
+ getCurScope(), ConstructorDecl, SS, TemplateTypeTy, ArgExprs, II,
+ T.getOpenLocation());
+ CalledSignatureHelp = true;
+ Actions.CodeCompleteExpression(getCurScope(), PreferredType);
+ })) {
+ if (PP.isCodeCompletionReached() && !CalledSignatureHelp) {
+ Actions.ProduceCtorInitMemberSignatureHelp(
+ getCurScope(), ConstructorDecl, SS, TemplateTypeTy, ArgExprs, II,
+ T.getOpenLocation());
+ CalledSignatureHelp = true;
+ }
SkipUntil(tok::r_paren, StopAtSemi);
return true;
}
@@ -3776,6 +3805,28 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) {
}
return nullptr;
+ case tok::numeric_constant: {
+ // If we got a numeric constant, check to see if it comes from a macro that
+ // corresponds to the predefined __clang__ macro. If it does, warn the user
+ // and recover by pretending they said _Clang instead.
+ if (Tok.getLocation().isMacroID()) {
+ SmallString<8> ExpansionBuf;
+ SourceLocation ExpansionLoc =
+ PP.getSourceManager().getExpansionLoc(Tok.getLocation());
+ StringRef Spelling = PP.getSpelling(ExpansionLoc, ExpansionBuf);
+ if (Spelling == "__clang__") {
+ SourceRange TokRange(
+ ExpansionLoc,
+ PP.getSourceManager().getExpansionLoc(Tok.getEndLoc()));
+ Diag(Tok, diag::warn_wrong_clang_attr_namespace)
+ << FixItHint::CreateReplacement(TokRange, "_Clang");
+ Loc = ConsumeToken();
+ return &PP.getIdentifierTable().get("_Clang");
+ }
+ }
+ return nullptr;
+ }
+
case tok::ampamp: // 'and'
case tok::pipe: // 'bitor'
case tok::pipepipe: // 'or'
@@ -3854,7 +3905,7 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
return false;
}
- if (ScopeName && ScopeName->getName() == "gnu") {
+ if (ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"))) {
// GNU-scoped attributes have some special cases to handle GNU-specific
// behaviors.
ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
@@ -3864,10 +3915,9 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
unsigned NumArgs;
// Some Clang-scoped attributes have some special parsing behavior.
- if (ScopeName && ScopeName->getName() == "clang")
- NumArgs =
- ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
- ScopeLoc, Syntax);
+ if (ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang")))
+ NumArgs = ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc,
+ ScopeName, ScopeLoc, Syntax);
else
NumArgs =
ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
@@ -3875,7 +3925,7 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
if (!Attrs.empty() &&
IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) {
- ParsedAttr &Attr = *Attrs.begin();
+ ParsedAttr &Attr = Attrs.back();
// If the attribute is a standard or built-in attribute and we are
// parsing an argument list, we need to determine whether this attribute
// was allowed to have an argument list (such as [[deprecated]]), and how