summaryrefslogtreecommitdiffstats
path: root/lib/Parse/ParseCXXInlineMethods.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2013-04-08 18:45:10 +0000
committerdim <dim@FreeBSD.org>2013-04-08 18:45:10 +0000
commitc72c57c9e9b69944e3e009cd5e209634839581d3 (patch)
tree4fc2f184c499d106f29a386c452b49e5197bf63d /lib/Parse/ParseCXXInlineMethods.cpp
parent5b20025c30d23d521e12c1f33ec8fa6b821952cd (diff)
downloadFreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.zip
FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.tar.gz
Vendor import of clang trunk r178860:
http://llvm.org/svn/llvm-project/cfe/trunk@178860
Diffstat (limited to 'lib/Parse/ParseCXXInlineMethods.cpp')
-rw-r--r--lib/Parse/ParseCXXInlineMethods.cpp55
1 files changed, 37 insertions, 18 deletions
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 9c5c0597..bc634b5 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -11,18 +11,25 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
+#include "RAIIObjectsForParser.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Scope.h"
-#include "clang/AST/DeclTemplate.h"
-#include "RAIIObjectsForParser.h"
using namespace clang;
+/// Get the FunctionDecl for a function or function template decl.
+static FunctionDecl *getFunctionDecl(Decl *D) {
+ if (FunctionDecl *fn = dyn_cast<FunctionDecl>(D))
+ return fn;
+ return cast<FunctionTemplateDecl>(D)->getTemplatedDecl();
+}
+
/// ParseCXXInlineMethodDef - We parsed and verified that the specified
/// 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.
-Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
+NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
AttributeList *AccessAttrs,
ParsingDeclarator &D,
const ParsedTemplateInfo &TemplateInfo,
@@ -38,7 +45,7 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data() : 0,
TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0);
- Decl *FnD;
+ NamedDecl *FnD;
D.setFunctionDefinitionKind(DefinitionKind);
if (D.getDeclSpec().isFriendSpecified())
FnD = Actions.ActOnFriendFunctionDecl(getCurScope(), D,
@@ -75,7 +82,7 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
bool Delete = false;
SourceLocation KWLoc;
if (Tok.is(tok::kw_delete)) {
- Diag(Tok, getLangOpts().CPlusPlus0x ?
+ Diag(Tok, getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_deleted_function :
diag::ext_deleted_function);
@@ -83,7 +90,7 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
Actions.SetDeclDeleted(FnD, KWLoc);
Delete = true;
} else if (Tok.is(tok::kw_default)) {
- Diag(Tok, getLangOpts().CPlusPlus0x ?
+ Diag(Tok, getLangOpts().CPlusPlus11 ?
diag::warn_cxx98_compat_defaulted_function :
diag::ext_defaulted_function);
@@ -117,11 +124,7 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
if (FnD) {
LateParsedTemplatedFunction *LPT = new LateParsedTemplatedFunction(FnD);
- FunctionDecl *FD = 0;
- if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(FnD))
- FD = FunTmpl->getTemplatedDecl();
- else
- FD = cast<FunctionDecl>(FnD);
+ FunctionDecl *FD = getFunctionDecl(FnD);
Actions.CheckForFunctionRedefinition(FD);
LateParsedTemplateMap[FD] = LPT;
@@ -176,6 +179,19 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
getCurrentClass().LateParsedDeclarations.pop_back();
}
+ // If this is a friend function, mark that it's late-parsed so that
+ // it's still known to be a definition even before we attach the
+ // parsed body. Sema needs to treat friend function definitions
+ // differently during template instantiation, and it's possible for
+ // the containing class to be instantiated before all its member
+ // function definitions are parsed.
+ //
+ // If you remove this, you can remove the code that clears the flag
+ // after parsing the member.
+ if (D.getDeclSpec().isFriendSpecified()) {
+ getFunctionDecl(FnD)->setLateTemplateParsed(true);
+ }
+
return FnD;
}
@@ -293,8 +309,8 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
// Introduce the parameters into scope and parse their default
// arguments.
- ParseScope PrototypeScope(this,
- Scope::FunctionPrototypeScope|Scope::DeclScope);
+ ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope |
+ Scope::FunctionDeclarationScope | Scope::DeclScope);
for (unsigned I = 0, N = LM.DefaultArgs.size(); I != N; ++I) {
// Introduce the parameter into scope.
Actions.ActOnDelayedCXXMethodParameter(getCurScope(),
@@ -322,7 +338,7 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) {
LM.DefaultArgs[I].Param);
ExprResult DefArgResult;
- if (getLangOpts().CPlusPlus0x && Tok.is(tok::l_brace)) {
+ if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
DefArgResult = ParseBraceInitializer();
} else
@@ -391,7 +407,7 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
PP.EnterTokenStream(LM.Toks.data(), LM.Toks.size(), true, false);
// Consume the previously pushed token.
- ConsumeAnyToken();
+ ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
&& "Inline method not starting with '{', ':' or 'try'");
@@ -427,6 +443,9 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
ParseFunctionStatementBody(LM.D, FnScope);
+ // Clear the late-template-parsed bit if we set it before.
+ if (LM.D) getFunctionDecl(LM.D)->setLateTemplateParsed(false);
+
if (Tok.getLocation() != origLoc) {
// Due to parsing error, we either went over the cached tokens or
// there are still cached tokens left. If it's the latter case skip the
@@ -491,7 +510,7 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) {
PP.EnterTokenStream(MI.Toks.data(), MI.Toks.size(), true, false);
// Consume the previously pushed token.
- ConsumeAnyToken();
+ ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
SourceLocation EqualLoc;
@@ -651,7 +670,7 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
ConsumeBrace();
// In C++03, this has to be the start of the function body, which
// means the initializer is malformed; we'll diagnose it later.
- if (!getLangOpts().CPlusPlus0x)
+ if (!getLangOpts().CPlusPlus11)
return false;
}
OpenPOWER on IntegriCloud