summaryrefslogtreecommitdiffstats
path: root/lib/Sema
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2012-05-03 16:53:59 +0000
committerdim <dim@FreeBSD.org>2012-05-03 16:53:59 +0000
commit822bde9df508e0b9afac5e581b0d6ab403417a28 (patch)
tree2e51705e103e92c7be1b21e8bd8ffd5b5d0e4d52 /lib/Sema
parent50b73317314e889cf39c7b1d6cbf419fa7502f22 (diff)
downloadFreeBSD-src-822bde9df508e0b9afac5e581b0d6ab403417a28.zip
FreeBSD-src-822bde9df508e0b9afac5e581b0d6ab403417a28.tar.gz
Vendor import of clang release_31 branch r155985:
http://llvm.org/svn/llvm-project/cfe/branches/release_31@155985
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/CMakeLists.txt1
-rw-r--r--lib/Sema/DeclSpec.cpp5
-rw-r--r--lib/Sema/Sema.cpp1
-rw-r--r--lib/Sema/SemaAccess.cpp7
-rw-r--r--lib/Sema/SemaDecl.cpp26
-rw-r--r--lib/Sema/SemaDeclCXX.cpp341
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp359
-rw-r--r--lib/Sema/SemaExpr.cpp33
-rw-r--r--lib/Sema/SemaExprCXX.cpp73
-rw-r--r--lib/Sema/SemaExprMember.cpp17
-rw-r--r--lib/Sema/SemaLookup.cpp45
-rw-r--r--lib/Sema/SemaOverload.cpp2
-rw-r--r--lib/Sema/SemaPseudoObject.cpp28
-rw-r--r--lib/Sema/SemaStmt.cpp11
-rw-r--r--lib/Sema/SemaStmtAttr.cpp48
-rw-r--r--lib/Sema/SemaTemplate.cpp4
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp49
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp101
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp363
-rw-r--r--lib/Sema/SemaType.cpp51
-rw-r--r--lib/Sema/TreeTransform.h66
21 files changed, 1305 insertions, 326 deletions
diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index 5d297f9..07734c7 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -40,6 +40,7 @@ add_clang_library(clangSema
SemaOverload.cpp
SemaPseudoObject.cpp
SemaStmt.cpp
+ SemaStmtAttr.cpp
SemaTemplate.cpp
SemaTemplateDeduction.cpp
SemaTemplateInstantiate.cpp
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index b531acc..fe63e35 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -162,6 +162,7 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
SourceRange *ExceptionRanges,
unsigned NumExceptions,
Expr *NoexceptExpr,
+ CachedTokens *ExceptionSpecTokens,
SourceLocation LocalRangeBegin,
SourceLocation LocalRangeEnd,
Declarator &TheDeclarator,
@@ -226,6 +227,10 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, bool isVariadic,
case EST_ComputedNoexcept:
I.Fun.NoexceptExpr = NoexceptExpr;
break;
+
+ case EST_Delayed:
+ I.Fun.ExceptionSpecTokens = ExceptionSpecTokens;
+ break;
}
return I;
}
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index fcdfcac..30a9cd7 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -103,6 +103,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
AnalysisWarnings(*this)
{
TUScope = 0;
+
LoadedExternalKnownNamespaces = false;
for (unsigned I = 0; I != NSAPI::NumNSNumberLiteralMethods; ++I)
NSNumberLiteralMethods[I] = 0;
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index dea5e76..01c141e 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -779,6 +779,13 @@ static AccessResult HasAccess(Sema &S,
// that the naming class has to be derived from the effective
// context.
+ // Emulate a MSVC bug where the creation of pointer-to-member
+ // to protected member of base class is allowed but only from
+ // a static function member functions.
+ if (S.getLangOpts().MicrosoftMode && !EC.Functions.empty())
+ if (CXXMethodDecl* MD = dyn_cast<CXXMethodDecl>(EC.Functions.front()))
+ if (MD->isStatic()) return AR_accessible;
+
// Despite the standard's confident wording, there is a case
// where you can have an instance member that's neither in a
// pointer-to-member expression nor in a member access: when
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 8b314b5..1550993 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -4471,6 +4471,11 @@ static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier,
return false;
}
+static bool hasDelayedExceptionSpec(CXXMethodDecl *Method) {
+ const FunctionProtoType *Proto =Method->getType()->getAs<FunctionProtoType>();
+ return Proto && Proto->getExceptionSpecType() == EST_Delayed;
+}
+
/// AddOverriddenMethods - See if a method overrides any in the base classes,
/// and if so, check that it's a valid override and remember it.
bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
@@ -4486,7 +4491,8 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
MD->addOverriddenMethod(OldMD->getCanonicalDecl());
if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
- !CheckOverridingFunctionExceptionSpec(MD, OldMD) &&
+ (hasDelayedExceptionSpec(MD) ||
+ !CheckOverridingFunctionExceptionSpec(MD, OldMD)) &&
!CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) {
AddedAny = true;
}
@@ -5834,6 +5840,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
}
}
}
+
+ if (Method->isStatic())
+ checkThisInStaticMemberFunctionType(Method);
}
// Extra checking for C++ overloaded operators (C++ [over.oper]).
@@ -7176,8 +7185,7 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
}
}
-Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope,
- Declarator &D) {
+Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
assert(getCurFunctionDecl() == 0 && "Function parsing confused");
assert(D.isFunctionDeclarator() && "Not a function declarator!");
Scope *ParentScope = FnBodyScope->getParent();
@@ -7350,6 +7358,10 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
}
}
+ // Ensure that the function's exception specification is instantiated.
+ if (const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>())
+ ResolveExceptionSpec(D->getLocation(), FPT);
+
// Checking attributes of current function definition
// dllimport attribute.
DLLImportAttr *DA = FD->getAttr<DLLImportAttr>();
@@ -7554,7 +7566,11 @@ void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D,
// Always attach attributes to the underlying decl.
if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
D = TD->getTemplatedDecl();
- ProcessDeclAttributeList(S, D, Attrs.getList());
+ ProcessDeclAttributeList(S, D, Attrs.getList());
+
+ if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(D))
+ if (Method->isStatic())
+ checkThisInStaticMemberFunctionAttributes(Method);
}
@@ -7619,7 +7635,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
SourceLocation(), SourceLocation(),
SourceLocation(),
EST_None, SourceLocation(),
- 0, 0, 0, 0, Loc, Loc, D),
+ 0, 0, 0, 0, 0, Loc, Loc, D),
DS.getAttributes(),
SourceLocation());
D.SetIdentifier(&II, Loc);
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 847f03c..1d251b9 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -25,6 +25,7 @@
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecordLayout.h"
+#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeOrdering.h"
@@ -124,14 +125,17 @@ namespace {
}
}
-void Sema::ImplicitExceptionSpecification::CalledDecl(CXXMethodDecl *Method) {
- assert(Context && "ImplicitExceptionSpecification without an ASTContext");
+void Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
+ CXXMethodDecl *Method) {
// If we have an MSAny or unknown spec already, don't bother.
if (!Method || ComputedEST == EST_MSAny || ComputedEST == EST_Delayed)
return;
const FunctionProtoType *Proto
= Method->getType()->getAs<FunctionProtoType>();
+ Proto = Self->ResolveExceptionSpec(CallLoc, Proto);
+ if (!Proto)
+ return;
ExceptionSpecificationType EST = Proto->getExceptionSpecType();
@@ -163,7 +167,8 @@ void Sema::ImplicitExceptionSpecification::CalledDecl(CXXMethodDecl *Method) {
// Check out noexcept specs.
if (EST == EST_ComputedNoexcept) {
- FunctionProtoType::NoexceptResult NR = Proto->getNoexceptSpec(*Context);
+ FunctionProtoType::NoexceptResult NR =
+ Proto->getNoexceptSpec(Self->Context);
assert(NR != FunctionProtoType::NR_NoNoexcept &&
"Must have noexcept result for EST_ComputedNoexcept.");
assert(NR != FunctionProtoType::NR_Dependent &&
@@ -187,7 +192,7 @@ void Sema::ImplicitExceptionSpecification::CalledDecl(CXXMethodDecl *Method) {
for (FunctionProtoType::exception_iterator E = Proto->exception_begin(),
EEnd = Proto->exception_end();
E != EEnd; ++E)
- if (ExceptionsSeen.insert(Context->getCanonicalType(*E)))
+ if (ExceptionsSeen.insert(Self->Context.getCanonicalType(*E)))
Exceptions.push_back(*E);
}
@@ -216,7 +221,7 @@ void Sema::ImplicitExceptionSpecification::CalledExpr(Expr *E) {
// implicit definition. For now, we assume that any non-nothrow expression can
// throw any exception.
- if (E->CanThrow(*Context))
+ if (Self->canThrow(E))
ComputedEST = EST_None;
}
@@ -3921,7 +3926,7 @@ void Sema::CheckExplicitlyDefaultedCopyConstructor(CXXConstructorDecl *CD) {
HadError = true;
}
- ImplicitExceptionSpecification Spec(Context);
+ ImplicitExceptionSpecification Spec(*this);
bool Const;
llvm::tie(Spec, Const) =
ComputeDefaultedCopyCtorExceptionSpecAndConst(CD->getParent());
@@ -4030,7 +4035,7 @@ void Sema::CheckExplicitlyDefaultedCopyAssignment(CXXMethodDecl *MD) {
HadError = true;
}
- ImplicitExceptionSpecification Spec(Context);
+ ImplicitExceptionSpecification Spec(*this);
bool Const;
llvm::tie(Spec, Const) =
ComputeDefaultedCopyCtorExceptionSpecAndConst(MD->getParent());
@@ -5920,10 +5925,12 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
case UnqualifiedId::IK_ConstructorName:
case UnqualifiedId::IK_ConstructorTemplateId:
- // C++0x inherited constructors.
+ // C++11 inheriting constructors.
Diag(Name.getLocStart(),
getLangOpts().CPlusPlus0x ?
- diag::warn_cxx98_compat_using_decl_constructor :
+ // FIXME: Produce warn_cxx98_compat_using_decl_constructor
+ // instead once inheriting constructors work.
+ diag::err_using_decl_constructor_unsupported :
diag::err_using_decl_constructor)
<< SS.getRange();
@@ -6813,7 +6820,7 @@ Sema::ComputeDefaultedDefaultCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
// C++ [except.spec]p14:
// An implicitly declared special member function (Clause 12) shall have an
// exception-specification. [...]
- ImplicitExceptionSpecification ExceptSpec(Context);
+ ImplicitExceptionSpecification ExceptSpec(*this);
if (ClassDecl->isInvalidDecl())
return ExceptSpec;
@@ -6830,7 +6837,7 @@ Sema::ComputeDefaultedDefaultCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
// If this is a deleted function, add it anyway. This might be conformant
// with the standard. This might not. I'm not sure. It might not matter.
if (Constructor)
- ExceptSpec.CalledDecl(Constructor);
+ ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
}
}
@@ -6844,7 +6851,7 @@ Sema::ComputeDefaultedDefaultCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
// If this is a deleted function, add it anyway. This might be conformant
// with the standard. This might not. I'm not sure. It might not matter.
if (Constructor)
- ExceptSpec.CalledDecl(Constructor);
+ ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
}
}
@@ -6867,7 +6874,7 @@ Sema::ComputeDefaultedDefaultCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
// might just be ill-formed because this function attempts to refer to
// a deleted function here.
if (Constructor)
- ExceptSpec.CalledDecl(Constructor);
+ ExceptSpec.CalledDecl(F->getLocation(), Constructor);
}
}
@@ -6989,6 +6996,7 @@ void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) {
const FunctionProtoType *CtorTy =
CtorDecl->getType()->castAs<FunctionProtoType>();
if (CtorTy->getExceptionSpecType() == EST_Delayed) {
+ // FIXME: Don't do this unless the exception spec is needed.
ImplicitExceptionSpecification Spec =
ComputeDefaultedDefaultCtorExceptionSpec(ClassDecl);
FunctionProtoType::ExtProtoInfo EPI = Spec.getEPI();
@@ -7189,7 +7197,7 @@ Sema::ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl) {
// C++ [except.spec]p14:
// An implicitly declared special member function (Clause 12) shall have
// an exception-specification.
- ImplicitExceptionSpecification ExceptSpec(Context);
+ ImplicitExceptionSpecification ExceptSpec(*this);
if (ClassDecl->isInvalidDecl())
return ExceptSpec;
@@ -7201,7 +7209,7 @@ Sema::ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl) {
continue;
if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
- ExceptSpec.CalledDecl(
+ ExceptSpec.CalledDecl(B->getLocStart(),
LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
}
@@ -7210,7 +7218,7 @@ Sema::ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl) {
BEnd = ClassDecl->vbases_end();
B != BEnd; ++B) {
if (const RecordType *BaseType = B->getType()->getAs<RecordType>())
- ExceptSpec.CalledDecl(
+ ExceptSpec.CalledDecl(B->getLocStart(),
LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
}
@@ -7220,7 +7228,7 @@ Sema::ComputeDefaultedDtorExceptionSpec(CXXRecordDecl *ClassDecl) {
F != FEnd; ++F) {
if (const RecordType *RecordTy
= Context.getBaseElementType(F->getType())->getAs<RecordType>())
- ExceptSpec.CalledDecl(
+ ExceptSpec.CalledDecl(F->getLocation(),
LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl())));
}
@@ -7545,7 +7553,7 @@ std::pair<Sema::ImplicitExceptionSpecification, bool>
Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(
CXXRecordDecl *ClassDecl) {
if (ClassDecl->isInvalidDecl())
- return std::make_pair(ImplicitExceptionSpecification(Context), false);
+ return std::make_pair(ImplicitExceptionSpecification(*this), false);
// C++ [class.copy]p10:
// If the class definition does not explicitly declare a copy
@@ -7618,7 +7626,7 @@ Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(
// Based on a similar decision made for constness in C++0x, we're erring on
// the side of assuming such calls to be made regardless of whether they
// actually happen.
- ImplicitExceptionSpecification ExceptSpec(Context);
+ ImplicitExceptionSpecification ExceptSpec(*this);
unsigned ArgQuals = HasConstCopyAssignment ? Qualifiers::Const : 0;
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
BaseEnd = ClassDecl->bases_end();
@@ -7630,7 +7638,7 @@ Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl,
ArgQuals, false, 0))
- ExceptSpec.CalledDecl(CopyAssign);
+ ExceptSpec.CalledDecl(Base->getLocStart(), CopyAssign);
}
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
@@ -7640,7 +7648,7 @@ Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl,
ArgQuals, false, 0))
- ExceptSpec.CalledDecl(CopyAssign);
+ ExceptSpec.CalledDecl(Base->getLocStart(), CopyAssign);
}
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
@@ -7651,7 +7659,7 @@ Sema::ComputeDefaultedCopyAssignmentExceptionSpecAndConst(
if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
if (CXXMethodDecl *CopyAssign =
LookupCopyingAssignment(FieldClassDecl, ArgQuals, false, 0))
- ExceptSpec.CalledDecl(CopyAssign);
+ ExceptSpec.CalledDecl(Field->getLocation(), CopyAssign);
}
}
@@ -7664,7 +7672,7 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
// for determining the argument type of the operator. Note also that
// operators taking an object instead of a reference are allowed.
- ImplicitExceptionSpecification Spec(Context);
+ ImplicitExceptionSpecification Spec(*this);
bool Const;
llvm::tie(Spec, Const) =
ComputeDefaultedCopyAssignmentExceptionSpecAndConst(ClassDecl);
@@ -8031,7 +8039,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
Sema::ImplicitExceptionSpecification
Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl *ClassDecl) {
- ImplicitExceptionSpecification ExceptSpec(Context);
+ ImplicitExceptionSpecification ExceptSpec(*this);
if (ClassDecl->isInvalidDecl())
return ExceptSpec;
@@ -8058,7 +8066,7 @@ Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl *ClassDecl) {
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl,
false, 0))
- ExceptSpec.CalledDecl(MoveAssign);
+ ExceptSpec.CalledDecl(Base->getLocStart(), MoveAssign);
}
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
@@ -8068,7 +8076,7 @@ Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl *ClassDecl) {
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl,
false, 0))
- ExceptSpec.CalledDecl(MoveAssign);
+ ExceptSpec.CalledDecl(Base->getLocStart(), MoveAssign);
}
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
@@ -8079,7 +8087,7 @@ Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXRecordDecl *ClassDecl) {
if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(FieldClassDecl,
false, 0))
- ExceptSpec.CalledDecl(MoveAssign);
+ ExceptSpec.CalledDecl(Field->getLocation(), MoveAssign);
}
}
@@ -8577,7 +8585,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
std::pair<Sema::ImplicitExceptionSpecification, bool>
Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) {
if (ClassDecl->isInvalidDecl())
- return std::make_pair(ImplicitExceptionSpecification(Context), false);
+ return std::make_pair(ImplicitExceptionSpecification(*this), false);
// C++ [class.copy]p5:
// The implicitly-declared copy constructor for a class X will
@@ -8638,7 +8646,7 @@ Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) {
// C++ [except.spec]p14:
// An implicitly declared special member function (Clause 12) shall have an
// exception-specification. [...]
- ImplicitExceptionSpecification ExceptSpec(Context);
+ ImplicitExceptionSpecification ExceptSpec(*this);
unsigned Quals = HasConstCopyConstructor? Qualifiers::Const : 0;
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
BaseEnd = ClassDecl->bases_end();
@@ -8652,7 +8660,7 @@ Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) {
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
if (CXXConstructorDecl *CopyConstructor =
LookupCopyingConstructor(BaseClassDecl, Quals))
- ExceptSpec.CalledDecl(CopyConstructor);
+ ExceptSpec.CalledDecl(Base->getLocStart(), CopyConstructor);
}
for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
BaseEnd = ClassDecl->vbases_end();
@@ -8662,7 +8670,7 @@ Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) {
= cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
if (CXXConstructorDecl *CopyConstructor =
LookupCopyingConstructor(BaseClassDecl, Quals))
- ExceptSpec.CalledDecl(CopyConstructor);
+ ExceptSpec.CalledDecl(Base->getLocStart(), CopyConstructor);
}
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
FieldEnd = ClassDecl->field_end();
@@ -8672,7 +8680,7 @@ Sema::ComputeDefaultedCopyCtorExceptionSpecAndConst(CXXRecordDecl *ClassDecl) {
if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
if (CXXConstructorDecl *CopyConstructor =
LookupCopyingConstructor(FieldClassDecl, Quals))
- ExceptSpec.CalledDecl(CopyConstructor);
+ ExceptSpec.CalledDecl(Field->getLocation(), CopyConstructor);
}
}
@@ -8685,7 +8693,7 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
// If the class definition does not explicitly declare a copy
// constructor, one is declared implicitly.
- ImplicitExceptionSpecification Spec(Context);
+ ImplicitExceptionSpecification Spec(*this);
bool Const;
llvm::tie(Spec, Const) =
ComputeDefaultedCopyCtorExceptionSpecAndConst(ClassDecl);
@@ -8783,7 +8791,7 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
// C++ [except.spec]p14:
// An implicitly declared special member function (Clause 12) shall have an
// exception-specification. [...]
- ImplicitExceptionSpecification ExceptSpec(Context);
+ ImplicitExceptionSpecification ExceptSpec(*this);
if (ClassDecl->isInvalidDecl())
return ExceptSpec;
@@ -8800,7 +8808,7 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
// If this is a deleted function, add it anyway. This might be conformant
// with the standard. This might not. I'm not sure. It might not matter.
if (Constructor)
- ExceptSpec.CalledDecl(Constructor);
+ ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
}
}
@@ -8814,7 +8822,7 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
// If this is a deleted function, add it anyway. This might be conformant
// with the standard. This might not. I'm not sure. It might not matter.
if (Constructor)
- ExceptSpec.CalledDecl(Constructor);
+ ExceptSpec.CalledDecl(B->getLocStart(), Constructor);
}
}
@@ -8832,7 +8840,7 @@ Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXRecordDecl *ClassDecl) {
// might just be ill-formed because this function attempts to refer to
// a deleted function here.
if (Constructor)
- ExceptSpec.CalledDecl(Constructor);
+ ExceptSpec.CalledDecl(F->getLocation(), Constructor);
}
}
@@ -11053,6 +11061,265 @@ void Sema::CheckDelegatingCtorCycles() {
(*CI)->setInvalidDecl();
}
+namespace {
+ /// \brief AST visitor that finds references to the 'this' expression.
+ class FindCXXThisExpr : public RecursiveASTVisitor<FindCXXThisExpr> {
+ Sema &S;
+
+ public:
+ explicit FindCXXThisExpr(Sema &S) : S(S) { }
+
+ bool VisitCXXThisExpr(CXXThisExpr *E) {
+ S.Diag(E->getLocation(), diag::err_this_static_member_func)
+ << E->isImplicit();
+ return false;
+ }
+ };
+}
+
+bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) {
+ TypeSourceInfo *TSInfo = Method->getTypeSourceInfo();
+ if (!TSInfo)
+ return false;
+
+ TypeLoc TL = TSInfo->getTypeLoc();
+ FunctionProtoTypeLoc *ProtoTL = dyn_cast<FunctionProtoTypeLoc>(&TL);
+ if (!ProtoTL)
+ return false;
+
+ // C++11 [expr.prim.general]p3:
+ // [The expression this] shall not appear before the optional
+ // cv-qualifier-seq and it shall not appear within the declaration of a
+ // static member function (although its type and value category are defined
+ // within a static member function as they are within a non-static member
+ // function). [ Note: this is because declaration matching does not occur
+ // until the complete declarator is known. - end note ]
+ const FunctionProtoType *Proto = ProtoTL->getTypePtr();
+ FindCXXThisExpr Finder(*this);
+
+ // If the return type came after the cv-qualifier-seq, check it now.
+ if (Proto->hasTrailingReturn() &&
+ !Finder.TraverseTypeLoc(ProtoTL->getResultLoc()))
+ return true;
+
+ // Check the exception specification.
+ if (checkThisInStaticMemberFunctionExceptionSpec(Method))
+ return true;
+
+ return checkThisInStaticMemberFunctionAttributes(Method);
+}
+
+bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) {
+ TypeSourceInfo *TSInfo = Method->getTypeSourceInfo();
+ if (!TSInfo)
+ return false;
+
+ TypeLoc TL = TSInfo->getTypeLoc();
+ FunctionProtoTypeLoc *ProtoTL = dyn_cast<FunctionProtoTypeLoc>(&TL);
+ if (!ProtoTL)
+ return false;
+
+ const FunctionProtoType *Proto = ProtoTL->getTypePtr();
+ FindCXXThisExpr Finder(*this);
+
+ switch (Proto->getExceptionSpecType()) {
+ case EST_Uninstantiated:
+ case EST_BasicNoexcept:
+ case EST_Delayed:
+ case EST_DynamicNone:
+ case EST_MSAny:
+ case EST_None:
+ break;
+
+ case EST_ComputedNoexcept:
+ if (!Finder.TraverseStmt(Proto->getNoexceptExpr()))
+ return true;
+
+ case EST_Dynamic:
+ for (FunctionProtoType::exception_iterator E = Proto->exception_begin(),
+ EEnd = Proto->exception_end();
+ E != EEnd; ++E) {
+ if (!Finder.TraverseType(*E))
+ return true;
+ }
+ break;
+ }
+
+ return false;
+}
+
+bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) {
+ FindCXXThisExpr Finder(*this);
+
+ // Check attributes.
+ for (Decl::attr_iterator A = Method->attr_begin(), AEnd = Method->attr_end();
+ A != AEnd; ++A) {
+ // FIXME: This should be emitted by tblgen.
+ Expr *Arg = 0;
+ ArrayRef<Expr *> Args;
+ if (GuardedByAttr *G = dyn_cast<GuardedByAttr>(*A))
+ Arg = G->getArg();
+ else if (PtGuardedByAttr *G = dyn_cast<PtGuardedByAttr>(*A))
+ Arg = G->getArg();
+ else if (AcquiredAfterAttr *AA = dyn_cast<AcquiredAfterAttr>(*A))
+ Args = ArrayRef<Expr *>(AA->args_begin(), AA->args_size());
+ else if (AcquiredBeforeAttr *AB = dyn_cast<AcquiredBeforeAttr>(*A))
+ Args = ArrayRef<Expr *>(AB->args_begin(), AB->args_size());
+ else if (ExclusiveLockFunctionAttr *ELF
+ = dyn_cast<ExclusiveLockFunctionAttr>(*A))
+ Args = ArrayRef<Expr *>(ELF->args_begin(), ELF->args_size());
+ else if (SharedLockFunctionAttr *SLF
+ = dyn_cast<SharedLockFunctionAttr>(*A))
+ Args = ArrayRef<Expr *>(SLF->args_begin(), SLF->args_size());
+ else if (ExclusiveTrylockFunctionAttr *ETLF
+ = dyn_cast<ExclusiveTrylockFunctionAttr>(*A)) {
+ Arg = ETLF->getSuccessValue();
+ Args = ArrayRef<Expr *>(ETLF->args_begin(), ETLF->args_size());
+ } else if (SharedTrylockFunctionAttr *STLF
+ = dyn_cast<SharedTrylockFunctionAttr>(*A)) {
+ Arg = STLF->getSuccessValue();
+ Args = ArrayRef<Expr *>(STLF->args_begin(), STLF->args_size());
+ } else if (UnlockFunctionAttr *UF = dyn_cast<UnlockFunctionAttr>(*A))
+ Args = ArrayRef<Expr *>(UF->args_begin(), UF->args_size());
+ else if (LockReturnedAttr *LR = dyn_cast<LockReturnedAttr>(*A))
+ Arg = LR->getArg();
+ else if (LocksExcludedAttr *LE = dyn_cast<LocksExcludedAttr>(*A))
+ Args = ArrayRef<Expr *>(LE->args_begin(), LE->args_size());
+ else if (ExclusiveLocksRequiredAttr *ELR
+ = dyn_cast<ExclusiveLocksRequiredAttr>(*A))
+ Args = ArrayRef<Expr *>(ELR->args_begin(), ELR->args_size());
+ else if (SharedLocksRequiredAttr *SLR
+ = dyn_cast<SharedLocksRequiredAttr>(*A))
+ Args = ArrayRef<Expr *>(SLR->args_begin(), SLR->args_size());
+
+ if (Arg && !Finder.TraverseStmt(Arg))
+ return true;
+
+ for (unsigned I = 0, N = Args.size(); I != N; ++I) {
+ if (!Finder.TraverseStmt(Args[I]))
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void
+Sema::checkExceptionSpecification(ExceptionSpecificationType EST,
+ ArrayRef<ParsedType> DynamicExceptions,
+ ArrayRef<SourceRange> DynamicExceptionRanges,
+ Expr *NoexceptExpr,
+ llvm::SmallVectorImpl<QualType> &Exceptions,
+ FunctionProtoType::ExtProtoInfo &EPI) {
+ Exceptions.clear();
+ EPI.ExceptionSpecType = EST;
+ if (EST == EST_Dynamic) {
+ Exceptions.reserve(DynamicExceptions.size());
+ for (unsigned ei = 0, ee = DynamicExceptions.size(); ei != ee; ++ei) {
+ // FIXME: Preserve type source info.
+ QualType ET = GetTypeFromParser(DynamicExceptions[ei]);
+
+ SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ collectUnexpandedParameterPacks(ET, Unexpanded);
+ if (!Unexpanded.empty()) {
+ DiagnoseUnexpandedParameterPacks(DynamicExceptionRanges[ei].getBegin(),
+ UPPC_ExceptionType,
+ Unexpanded);
+ continue;
+ }
+
+ // Check that the type is valid for an exception spec, and
+ // drop it if not.
+ if (!CheckSpecifiedExceptionType(ET, DynamicExceptionRanges[ei]))
+ Exceptions.push_back(ET);
+ }
+ EPI.NumExceptions = Exceptions.size();
+ EPI.Exceptions = Exceptions.data();
+ return;
+ }
+
+ if (EST == EST_ComputedNoexcept) {
+ // If an error occurred, there's no expression here.
+ if (NoexceptExpr) {
+ assert((NoexceptExpr->isTypeDependent() ||
+ NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==
+ Context.BoolTy) &&
+ "Parser should have made sure that the expression is boolean");
+ if (NoexceptExpr && DiagnoseUnexpandedParameterPack(NoexceptExpr)) {
+ EPI.ExceptionSpecType = EST_BasicNoexcept;
+ return;
+ }
+
+ if (!NoexceptExpr->isValueDependent())
+ NoexceptExpr = VerifyIntegerConstantExpression(NoexceptExpr, 0,
+ PDiag(diag::err_noexcept_needs_constant_expression),
+ /*AllowFold*/ false).take();
+ EPI.NoexceptExpr = NoexceptExpr;
+ }
+ return;
+ }
+}
+
+void Sema::actOnDelayedExceptionSpecification(Decl *MethodD,
+ ExceptionSpecificationType EST,
+ SourceRange SpecificationRange,
+ ArrayRef<ParsedType> DynamicExceptions,
+ ArrayRef<SourceRange> DynamicExceptionRanges,
+ Expr *NoexceptExpr) {
+ if (!MethodD)
+ return;
+
+ // Dig out the method we're referring to.
+ CXXMethodDecl *Method = 0;
+ if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(MethodD))
+ Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
+ else
+ Method = dyn_cast<CXXMethodDecl>(MethodD);
+
+ if (!Method)
+ return;
+
+ // Dig out the prototype. This should never fail.
+ const FunctionProtoType *Proto
+ = dyn_cast<FunctionProtoType>(Method->getType());
+ if (!Proto)
+ return;
+
+ // Check the exception specification.
+ llvm::SmallVector<QualType, 4> Exceptions;
+ FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
+ checkExceptionSpecification(EST, DynamicExceptions, DynamicExceptionRanges,
+ NoexceptExpr, Exceptions, EPI);
+
+ // Rebuild the function type.
+ QualType T = Context.getFunctionType(Proto->getResultType(),
+ Proto->arg_type_begin(),
+ Proto->getNumArgs(),
+ EPI);
+ if (TypeSourceInfo *TSInfo = Method->getTypeSourceInfo()) {
+ // FIXME: When we get proper type location information for exceptions,
+ // we'll also have to rebuild the TypeSourceInfo. For now, we just patch
+ // up the TypeSourceInfo;
+ assert(TypeLoc::getFullDataSizeForType(T)
+ == TypeLoc::getFullDataSizeForType(Method->getType()) &&
+ "TypeLoc size mismatch with delayed exception specification");
+ TSInfo->overrideType(T);
+ }
+
+ Method->setType(T);
+
+ if (Method->isStatic())
+ checkThisInStaticMemberFunctionExceptionSpec(Method);
+
+ if (Method->isVirtual()) {
+ // Check overrides, which we previously had to delay.
+ for (CXXMethodDecl::method_iterator O = Method->begin_overridden_methods(),
+ OEnd = Method->end_overridden_methods();
+ O != OEnd; ++O)
+ CheckOverridingFunctionExceptionSpec(Method, *O);
+ }
+}
+
/// IdentifyCUDATarget - Determine the CUDA compilation target for this function
Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const FunctionDecl *D) {
// Implicitly declared functions (e.g. copy constructors) are
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index 42221f8..14b2434 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -96,6 +96,26 @@ bool Sema::CheckDistantExceptionSpec(QualType T) {
return FnT->hasExceptionSpec();
}
+const FunctionProtoType *
+Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) {
+ // FIXME: If FD is a special member, we should delay computing its exception
+ // specification until this point.
+ if (FPT->getExceptionSpecType() != EST_Uninstantiated)
+ return FPT;
+
+ FunctionDecl *SourceDecl = FPT->getExceptionSpecDecl();
+ const FunctionProtoType *SourceFPT =
+ SourceDecl->getType()->castAs<FunctionProtoType>();
+
+ if (SourceFPT->getExceptionSpecType() != EST_Uninstantiated)
+ return SourceFPT;
+
+ // Instantiate the exception specification now.
+ InstantiateExceptionSpec(Loc, SourceDecl);
+
+ return SourceDecl->getType()->castAs<FunctionProtoType>();
+}
+
bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
OverloadedOperatorKind OO = New->getDeclName().getCXXOverloadedOperator();
bool IsOperatorNew = OO == OO_New || OO == OO_Array_New;
@@ -104,7 +124,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
unsigned DiagID = diag::err_mismatched_exception_spec;
if (getLangOpts().MicrosoftExt)
DiagID = diag::warn_mismatched_exception_spec;
-
+
if (!CheckEquivalentExceptionSpec(PDiag(DiagID),
PDiag(diag::note_previous_declaration),
Old->getType()->getAs<FunctionProtoType>(),
@@ -295,6 +315,13 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
if (MissingEmptyExceptionSpecification)
*MissingEmptyExceptionSpecification = false;
+ Old = ResolveExceptionSpec(NewLoc, Old);
+ if (!Old)
+ return false;
+ New = ResolveExceptionSpec(NewLoc, New);
+ if (!New)
+ return false;
+
// C++0x [except.spec]p3: Two exception-specifications are compatible if:
// - both are non-throwing, regardless of their form,
// - both have the form noexcept(constant-expression) and the constant-
@@ -318,6 +345,7 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
ExceptionSpecificationType NewEST = New->getExceptionSpecType();
assert(OldEST != EST_Delayed && NewEST != EST_Delayed &&
+ OldEST != EST_Uninstantiated && NewEST != EST_Uninstantiated &&
"Shouldn't see unknown exception specifications here");
// Shortcut the case where both have no spec.
@@ -483,6 +511,14 @@ bool Sema::CheckExceptionSpecSubset(
if (!SubLoc.isValid())
SubLoc = SuperLoc;
+ // Resolve the exception specifications, if needed.
+ Superset = ResolveExceptionSpec(SuperLoc, Superset);
+ if (!Superset)
+ return false;
+ Subset = ResolveExceptionSpec(SubLoc, Subset);
+ if (!Subset)
+ return false;
+
ExceptionSpecificationType SuperEST = Superset->getExceptionSpecType();
// If superset contains everything, we're done.
@@ -507,6 +543,7 @@ bool Sema::CheckExceptionSpecSubset(
ExceptionSpecificationType SubEST = Subset->getExceptionSpecType();
assert(SuperEST != EST_Delayed && SubEST != EST_Delayed &&
+ SuperEST != EST_Uninstantiated && SubEST != EST_Uninstantiated &&
"Shouldn't see unknown exception specifications here");
// It does not. If the subset contains everything, we've failed.
@@ -726,4 +763,324 @@ bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
New->getLocation());
}
+static CanThrowResult canSubExprsThrow(Sema &S, const Expr *CE) {
+ Expr *E = const_cast<Expr*>(CE);
+ CanThrowResult R = CT_Cannot;
+ for (Expr::child_range I = E->children(); I && R != CT_Can; ++I)
+ R = mergeCanThrow(R, S.canThrow(cast<Expr>(*I)));
+ return R;
+}
+
+static CanThrowResult canCalleeThrow(Sema &S, const Expr *E,
+ const Decl *D,
+ bool NullThrows = true) {
+ if (!D)
+ return NullThrows ? CT_Can : CT_Cannot;
+
+ // See if we can get a function type from the decl somehow.
+ const ValueDecl *VD = dyn_cast<ValueDecl>(D);
+ if (!VD) // If we have no clue what we're calling, assume the worst.
+ return CT_Can;
+
+ // As an extension, we assume that __attribute__((nothrow)) functions don't
+ // throw.
+ if (isa<FunctionDecl>(D) && D->hasAttr<NoThrowAttr>())
+ return CT_Cannot;
+
+ QualType T = VD->getType();
+ const FunctionProtoType *FT;
+ if ((FT = T->getAs<FunctionProtoType>())) {
+ } else if (const PointerType *PT = T->getAs<PointerType>())
+ FT = PT->getPointeeType()->getAs<FunctionProtoType>();
+ else if (const ReferenceType *RT = T->getAs<ReferenceType>())
+ FT = RT->getPointeeType()->getAs<FunctionProtoType>();
+ else if (const MemberPointerType *MT = T->getAs<MemberPointerType>())
+ FT = MT->getPointeeType()->getAs<FunctionProtoType>();
+ else if (const BlockPointerType *BT = T->getAs<BlockPointerType>())
+ FT = BT->getPointeeType()->getAs<FunctionProtoType>();
+
+ if (!FT)
+ return CT_Can;
+
+ FT = S.ResolveExceptionSpec(E->getLocStart(), FT);
+ if (!FT)
+ return CT_Can;
+
+ if (FT->getExceptionSpecType() == EST_Delayed) {
+ // FIXME: Try to resolve a delayed exception spec in ResolveExceptionSpec.
+ assert(isa<CXXConstructorDecl>(D) &&
+ "only constructor exception specs can be unknown");
+ S.Diag(E->getLocStart(), diag::err_exception_spec_unknown)
+ << E->getSourceRange();
+ return CT_Can;
+ }
+
+ return FT->isNothrow(S.Context) ? CT_Cannot : CT_Can;
+}
+
+static CanThrowResult canDynamicCastThrow(const CXXDynamicCastExpr *DC) {
+ if (DC->isTypeDependent())
+ return CT_Dependent;
+
+ if (!DC->getTypeAsWritten()->isReferenceType())
+ return CT_Cannot;
+
+ if (DC->getSubExpr()->isTypeDependent())
+ return CT_Dependent;
+
+ return DC->getCastKind() == clang::CK_Dynamic? CT_Can : CT_Cannot;
+}
+
+static CanThrowResult canTypeidThrow(Sema &S, const CXXTypeidExpr *DC) {
+ if (DC->isTypeOperand())
+ return CT_Cannot;
+
+ Expr *Op = DC->getExprOperand();
+ if (Op->isTypeDependent())
+ return CT_Dependent;
+
+ const RecordType *RT = Op->getType()->getAs<RecordType>();
+ if (!RT)
+ return CT_Cannot;
+
+ if (!cast<CXXRecordDecl>(RT->getDecl())->isPolymorphic())
+ return CT_Cannot;
+
+ if (Op->Classify(S.Context).isPRValue())
+ return CT_Cannot;
+
+ return CT_Can;
+}
+
+CanThrowResult Sema::canThrow(const Expr *E) {
+ // C++ [expr.unary.noexcept]p3:
+ // [Can throw] if in a potentially-evaluated context the expression would
+ // contain:
+ switch (E->getStmtClass()) {
+ case Expr::CXXThrowExprClass:
+ // - a potentially evaluated throw-expression
+ return CT_Can;
+
+ case Expr::CXXDynamicCastExprClass: {
+ // - a potentially evaluated dynamic_cast expression dynamic_cast<T>(v),
+ // where T is a reference type, that requires a run-time check
+ CanThrowResult CT = canDynamicCastThrow(cast<CXXDynamicCastExpr>(E));
+ if (CT == CT_Can)
+ return CT;
+ return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+ }
+
+ case Expr::CXXTypeidExprClass:
+ // - a potentially evaluated typeid expression applied to a glvalue
+ // expression whose type is a polymorphic class type
+ return canTypeidThrow(*this, cast<CXXTypeidExpr>(E));
+
+ // - a potentially evaluated call to a function, member function, function
+ // pointer, or member function pointer that does not have a non-throwing
+ // exception-specification
+ case Expr::CallExprClass:
+ case Expr::CXXMemberCallExprClass:
+ case Expr::CXXOperatorCallExprClass:
+ case Expr::UserDefinedLiteralClass: {
+ const CallExpr *CE = cast<CallExpr>(E);
+ CanThrowResult CT;
+ if (E->isTypeDependent())
+ CT = CT_Dependent;
+ else if (isa<CXXPseudoDestructorExpr>(CE->getCallee()->IgnoreParens()))
+ CT = CT_Cannot;
+ else
+ CT = canCalleeThrow(*this, E, CE->getCalleeDecl());
+ if (CT == CT_Can)
+ return CT;
+ return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+ }
+
+ case Expr::CXXConstructExprClass:
+ case Expr::CXXTemporaryObjectExprClass: {
+ CanThrowResult CT = canCalleeThrow(*this, E,
+ cast<CXXConstructExpr>(E)->getConstructor());
+ if (CT == CT_Can)
+ return CT;
+ return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+ }
+
+ case Expr::LambdaExprClass: {
+ const LambdaExpr *Lambda = cast<LambdaExpr>(E);
+ CanThrowResult CT = CT_Cannot;
+ for (LambdaExpr::capture_init_iterator Cap = Lambda->capture_init_begin(),
+ CapEnd = Lambda->capture_init_end();
+ Cap != CapEnd; ++Cap)
+ CT = mergeCanThrow(CT, canThrow(*Cap));
+ return CT;
+ }
+
+ case Expr::CXXNewExprClass: {
+ CanThrowResult CT;
+ if (E->isTypeDependent())
+ CT = CT_Dependent;
+ else
+ CT = canCalleeThrow(*this, E, cast<CXXNewExpr>(E)->getOperatorNew());
+ if (CT == CT_Can)
+ return CT;
+ return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+ }
+
+ case Expr::CXXDeleteExprClass: {
+ CanThrowResult CT;
+ QualType DTy = cast<CXXDeleteExpr>(E)->getDestroyedType();
+ if (DTy.isNull() || DTy->isDependentType()) {
+ CT = CT_Dependent;
+ } else {
+ CT = canCalleeThrow(*this, E,
+ cast<CXXDeleteExpr>(E)->getOperatorDelete());
+ if (const RecordType *RT = DTy->getAs<RecordType>()) {
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
+ CT = mergeCanThrow(CT, canCalleeThrow(*this, E, RD->getDestructor()));
+ }
+ if (CT == CT_Can)
+ return CT;
+ }
+ return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+ }
+
+ case Expr::CXXBindTemporaryExprClass: {
+ // The bound temporary has to be destroyed again, which might throw.
+ CanThrowResult CT = canCalleeThrow(*this, E,
+ cast<CXXBindTemporaryExpr>(E)->getTemporary()->getDestructor());
+ if (CT == CT_Can)
+ return CT;
+ return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+ }
+
+ // ObjC message sends are like function calls, but never have exception
+ // specs.
+ case Expr::ObjCMessageExprClass:
+ case Expr::ObjCPropertyRefExprClass:
+ case Expr::ObjCSubscriptRefExprClass:
+ return CT_Can;
+
+ // All the ObjC literals that are implemented as calls are
+ // potentially throwing unless we decide to close off that
+ // possibility.
+ case Expr::ObjCArrayLiteralClass:
+ case Expr::ObjCDictionaryLiteralClass:
+ case Expr::ObjCNumericLiteralClass:
+ return CT_Can;
+
+ // Many other things have subexpressions, so we have to test those.
+ // Some are simple:
+ case Expr::ConditionalOperatorClass:
+ case Expr::CompoundLiteralExprClass:
+ case Expr::CXXConstCastExprClass:
+ case Expr::CXXDefaultArgExprClass:
+ case Expr::CXXReinterpretCastExprClass:
+ case Expr::DesignatedInitExprClass:
+ case Expr::ExprWithCleanupsClass:
+ case Expr::ExtVectorElementExprClass:
+ case Expr::InitListExprClass:
+ case Expr::MemberExprClass:
+ case Expr::ObjCIsaExprClass:
+ case Expr::ObjCIvarRefExprClass:
+ case Expr::ParenExprClass:
+ case Expr::ParenListExprClass:
+ case Expr::ShuffleVectorExprClass:
+ case Expr::VAArgExprClass:
+ return canSubExprsThrow(*this, E);
+
+ // Some might be dependent for other reasons.
+ case Expr::ArraySubscriptExprClass:
+ case Expr::BinaryOperatorClass:
+ case Expr::CompoundAssignOperatorClass:
+ case Expr::CStyleCastExprClass:
+ case Expr::CXXStaticCastExprClass:
+ case Expr::CXXFunctionalCastExprClass:
+ case Expr::ImplicitCastExprClass:
+ case Expr::MaterializeTemporaryExprClass:
+ case Expr::UnaryOperatorClass: {
+ CanThrowResult CT = E->isTypeDependent() ? CT_Dependent : CT_Cannot;
+ return mergeCanThrow(CT, canSubExprsThrow(*this, E));
+ }
+
+ // FIXME: We should handle StmtExpr, but that opens a MASSIVE can of worms.
+ case Expr::StmtExprClass:
+ return CT_Can;
+
+ case Expr::ChooseExprClass:
+ if (E->isTypeDependent() || E->isValueDependent())
+ return CT_Dependent;
+ return canThrow(cast<ChooseExpr>(E)->getChosenSubExpr(Context));
+
+ case Expr::GenericSelectionExprClass:
+ if (cast<GenericSelectionExpr>(E)->isResultDependent())
+ return CT_Dependent;
+ return canThrow(cast<GenericSelectionExpr>(E)->getResultExpr());
+
+ // Some expressions are always dependent.
+ case Expr::CXXDependentScopeMemberExprClass:
+ case Expr::CXXUnresolvedConstructExprClass:
+ case Expr::DependentScopeDeclRefExprClass:
+ return CT_Dependent;
+
+ case Expr::AsTypeExprClass:
+ case Expr::BinaryConditionalOperatorClass:
+ case Expr::BlockExprClass:
+ case Expr::CUDAKernelCallExprClass:
+ case Expr::DeclRefExprClass:
+ case Expr::ObjCBridgedCastExprClass:
+ case Expr::ObjCIndirectCopyRestoreExprClass:
+ case Expr::ObjCProtocolExprClass:
+ case Expr::ObjCSelectorExprClass:
+ case Expr::OffsetOfExprClass:
+ case Expr::PackExpansionExprClass:
+ case Expr::PseudoObjectExprClass:
+ case Expr::SubstNonTypeTemplateParmExprClass:
+ case Expr::SubstNonTypeTemplateParmPackExprClass:
+ case Expr::UnaryExprOrTypeTraitExprClass:
+ case Expr::UnresolvedLookupExprClass:
+ case Expr::UnresolvedMemberExprClass:
+ // FIXME: Can any of the above throw? If so, when?
+ return CT_Cannot;
+
+ case Expr::AddrLabelExprClass:
+ case Expr::ArrayTypeTraitExprClass:
+ case Expr::AtomicExprClass:
+ case Expr::BinaryTypeTraitExprClass:
+ case Expr::TypeTraitExprClass:
+ case Expr::CXXBoolLiteralExprClass:
+ case Expr::CXXNoexceptExprClass:
+ case Expr::CXXNullPtrLiteralExprClass:
+ case Expr::CXXPseudoDestructorExprClass:
+ case Expr::CXXScalarValueInitExprClass:
+ case Expr::CXXThisExprClass:
+ case Expr::CXXUuidofExprClass:
+ case Expr::CharacterLiteralClass:
+ case Expr::ExpressionTraitExprClass:
+ case Expr::FloatingLiteralClass:
+ case Expr::GNUNullExprClass:
+ case Expr::ImaginaryLiteralClass:
+ case Expr::ImplicitValueInitExprClass:
+ case Expr::IntegerLiteralClass:
+ case Expr::ObjCEncodeExprClass:
+ case Expr::ObjCStringLiteralClass:
+ case Expr::ObjCBoolLiteralExprClass:
+ case Expr::OpaqueValueExprClass:
+ case Expr::PredefinedExprClass:
+ case Expr::SizeOfPackExprClass:
+ case Expr::StringLiteralClass:
+ case Expr::UnaryTypeTraitExprClass:
+ // These expressions can never throw.
+ return CT_Cannot;
+
+#define STMT(CLASS, PARENT) case Expr::CLASS##Class:
+#define STMT_RANGE(Base, First, Last)
+#define LAST_STMT_RANGE(BASE, FIRST, LAST)
+#define EXPR(CLASS, PARENT)
+#define ABSTRACT_STMT(STMT)
+#include "clang/AST/StmtNodes.inc"
+ case Expr::NoStmtClass:
+ llvm_unreachable("Invalid class for expression");
+ }
+ llvm_unreachable("Bogus StmtClass");
+}
+
} // end namespace clang
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 0d0f2f5..d2e0e6b 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -9438,10 +9438,11 @@ ExprResult Sema::VerifyIntegerConstantExpression(Expr *E,
PDiag(diag::err_expr_not_ice) << LangOpts.CPlusPlus);
}
-ExprResult Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
- PartialDiagnostic NotIceDiag,
- bool AllowFold,
- PartialDiagnostic FoldDiag) {
+ExprResult
+Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
+ const PartialDiagnostic &NotIceDiag,
+ bool AllowFold,
+ const PartialDiagnostic &FoldDiag) {
SourceLocation DiagLoc = E->getLocStart();
if (getLangOpts().CPlusPlus0x) {
@@ -9773,6 +9774,12 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) {
// FIXME: Is this really right?
if (CurContext == Func) return;
+ // Instantiate the exception specification for any function which is
+ // used: CodeGen will need it.
+ const FunctionProtoType *FPT = Func->getType()->getAs<FunctionProtoType>();
+ if (FPT && FPT->getExceptionSpecType() == EST_Uninstantiated)
+ InstantiateExceptionSpec(Loc, Func);
+
// Implicit instantiation of function templates and member functions of
// class templates.
if (Func->isImplicitlyInstantiable()) {
@@ -11268,22 +11275,6 @@ ExprResult
Sema::ActOnObjCBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) {
assert((Kind == tok::kw___objc_yes || Kind == tok::kw___objc_no) &&
"Unknown Objective-C Boolean value!");
- QualType ObjCBoolLiteralQT = Context.ObjCBuiltinBoolTy;
- // signed char is the default type for boolean literals. Use 'BOOL'
- // instead, if BOOL typedef is visible in its scope instead.
- Decl *TD =
- LookupSingleName(TUScope, &Context.Idents.get("BOOL"),
- SourceLocation(), LookupOrdinaryName);
- if (TypedefDecl *BoolTD = dyn_cast_or_null<TypedefDecl>(TD)) {
- QualType QT = BoolTD->getUnderlyingType();
- if (!QT->isIntegralOrUnscopedEnumerationType()) {
- Diag(OpLoc, diag::warn_bool_for_boolean_literal) << QT;
- Diag(BoolTD->getLocation(), diag::note_previous_declaration);
- }
- else
- ObjCBoolLiteralQT = QT;
- }
-
return Owned(new (Context) ObjCBoolLiteralExpr(Kind == tok::kw___objc_yes,
- ObjCBoolLiteralQT, OpLoc));
+ Context.ObjCBuiltinBoolTy, OpLoc));
}
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 31a8115..af86cb2 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -654,23 +654,44 @@ ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
QualType Sema::getCurrentThisType() {
DeclContext *DC = getFunctionLevelDeclContext();
- QualType ThisTy;
+ QualType ThisTy = CXXThisTypeOverride;
if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC)) {
if (method && method->isInstance())
ThisTy = method->getThisType(Context);
- } else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
- // C++0x [expr.prim]p4:
- // Otherwise, if a member-declarator declares a non-static data member
- // of a class X, the expression this is a prvalue of type "pointer to X"
- // within the optional brace-or-equal-initializer.
- Scope *S = getScopeForContext(DC);
- if (!S || S->getFlags() & Scope::ThisScope)
- ThisTy = Context.getPointerType(Context.getRecordType(RD));
}
-
+
return ThisTy;
}
+Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S,
+ Decl *ContextDecl,
+ unsigned CXXThisTypeQuals,
+ bool Enabled)
+ : S(S), OldCXXThisTypeOverride(S.CXXThisTypeOverride), Enabled(false)
+{
+ if (!Enabled || !ContextDecl)
+ return;
+
+ CXXRecordDecl *Record = 0;
+ if (ClassTemplateDecl *Template = dyn_cast<ClassTemplateDecl>(ContextDecl))
+ Record = Template->getTemplatedDecl();
+ else
+ Record = cast<CXXRecordDecl>(ContextDecl);
+
+ S.CXXThisTypeOverride
+ = S.Context.getPointerType(
+ S.Context.getRecordType(Record).withCVRQualifiers(CXXThisTypeQuals));
+
+ this->Enabled = true;
+}
+
+
+Sema::CXXThisScopeRAII::~CXXThisScopeRAII() {
+ if (Enabled) {
+ S.CXXThisTypeOverride = OldCXXThisTypeOverride;
+ }
+}
+
void Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit) {
// We don't need to capture this in an unevaluated context.
if (ExprEvalContexts.back().Context == Unevaluated && !Explicit)
@@ -739,6 +760,18 @@ ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {
return Owned(new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/false));
}
+bool Sema::isThisOutsideMemberFunctionBody(QualType BaseType) {
+ // If we're outside the body of a member function, then we'll have a specified
+ // type for 'this'.
+ if (CXXThisTypeOverride.isNull())
+ return false;
+
+ // Determine whether we're looking into a class that's currently being
+ // defined.
+ CXXRecordDecl *Class = BaseType->getAsCXXRecordDecl();
+ return Class && Class->isBeingDefined();
+}
+
ExprResult
Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep,
SourceLocation LParenLoc,
@@ -3102,6 +3135,9 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
FoundAssign = true;
const FunctionProtoType *CPT
= Operator->getType()->getAs<FunctionProtoType>();
+ CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
+ if (!CPT)
+ return false;
if (CPT->getExceptionSpecType() == EST_Delayed)
return false;
if (!CPT->isNothrow(Self.Context))
@@ -3141,6 +3177,9 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
FoundConstructor = true;
const FunctionProtoType *CPT
= Constructor->getType()->getAs<FunctionProtoType>();
+ CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
+ if (!CPT)
+ return false;
if (CPT->getExceptionSpecType() == EST_Delayed)
return false;
// FIXME: check whether evaluating default arguments can throw.
@@ -3176,6 +3215,9 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, UnaryTypeTrait UTT,
if (Constructor->isDefaultConstructor()) {
const FunctionProtoType *CPT
= Constructor->getType()->getAs<FunctionProtoType>();
+ CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
+ if (!CPT)
+ return false;
if (CPT->getExceptionSpecType() == EST_Delayed)
return false;
// TODO: check whether evaluating default arguments can throw.
@@ -4784,8 +4826,13 @@ Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc,
return Owned(Base);
}
- // The object type must be complete (or dependent).
+ // The object type must be complete (or dependent), or
+ // C++11 [expr.prim.general]p3:
+ // Unlike the object expression in other contexts, *this is not required to
+ // be of complete type for purposes of class member access (5.2.5) outside
+ // the member function body.
if (!BaseType->isDependentType() &&
+ !isThisOutsideMemberFunctionBody(BaseType) &&
RequireCompleteType(OpLoc, BaseType,
PDiag(diag::err_incomplete_member_access)))
return ExprError();
@@ -5165,9 +5212,9 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
ExprResult Sema::BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand,
SourceLocation RParen) {
+ CanThrowResult CanThrow = canThrow(Operand);
return Owned(new (Context) CXXNoexceptExpr(Context.BoolTy, Operand,
- Operand->CanThrow(Context),
- KeyLoc, RParen));
+ CanThrow, KeyLoc, RParen));
}
ExprResult Sema::ActOnNoexceptExpr(SourceLocation KeyLoc, SourceLocation,
diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index 26b88a2..6c84caa 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -101,16 +101,8 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
DeclContext *DC = SemaRef.getFunctionLevelDeclContext();
- bool isStaticContext =
- (!isa<CXXMethodDecl>(DC) ||
- cast<CXXMethodDecl>(DC)->isStatic());
-
- // C++0x [expr.prim]p4:
- // Otherwise, if a member-declarator declares a non-static data member
- // of a class X, the expression this is a prvalue of type "pointer to X"
- // within the optional brace-or-equal-initializer.
- if (CurScope->getFlags() & Scope::ThisScope)
- isStaticContext = false;
+ bool isStaticContext = SemaRef.CXXThisTypeOverride.isNull() &&
+ (!isa<CXXMethodDecl>(DC) || cast<CXXMethodDecl>(DC)->isStatic());
if (R.isUnresolvableResult())
return isStaticContext ? IMA_Unresolved_StaticContext : IMA_Unresolved;
@@ -549,12 +541,13 @@ class RecordMemberExprValidatorCCC : public CorrectionCandidateCallback {
}
static bool
-LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
+LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
SourceRange BaseRange, const RecordType *RTy,
SourceLocation OpLoc, CXXScopeSpec &SS,
bool HasTemplateArgs) {
RecordDecl *RDecl = RTy->getDecl();
- if (SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0),
+ if (!SemaRef.isThisOutsideMemberFunctionBody(QualType(RTy, 0)) &&
+ SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0),
SemaRef.PDiag(diag::err_typecheck_incomplete_tag)
<< BaseRange))
return true;
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 966eb90..f003bdd 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -3165,7 +3165,7 @@ LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
namespace {
typedef llvm::StringMap<TypoCorrection, llvm::BumpPtrAllocator> TypoResultsMap;
-typedef std::map<unsigned, TypoResultsMap *> TypoEditDistanceMap;
+typedef std::map<unsigned, TypoResultsMap> TypoEditDistanceMap;
static const unsigned MaxTypoDistanceResultSets = 5;
@@ -3187,14 +3187,6 @@ public:
: Typo(Typo->getName()),
SemaRef(SemaRef) { }
- ~TypoCorrectionConsumer() {
- for (TypoEditDistanceMap::iterator I = BestResults.begin(),
- IEnd = BestResults.end();
- I != IEnd;
- ++I)
- delete I->second;
- }
-
virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
bool InBaseClass);
void FoundName(StringRef Name);
@@ -3212,7 +3204,7 @@ public:
bool empty() const { return BestResults.empty(); }
TypoCorrection &operator[](StringRef Name) {
- return (*BestResults.begin()->second)[Name];
+ return BestResults.begin()->second[Name];
}
unsigned getBestEditDistance(bool Normalized) {
@@ -3276,11 +3268,9 @@ void TypoCorrectionConsumer::addName(StringRef Name,
void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) {
StringRef Name = Correction.getCorrectionAsIdentifierInfo()->getName();
- TypoResultsMap *& Map = BestResults[Correction.getEditDistance(false)];
- if (!Map)
- Map = new TypoResultsMap;
+ TypoResultsMap &Map = BestResults[Correction.getEditDistance(false)];
- TypoCorrection &CurrentCorrection = (*Map)[Name];
+ TypoCorrection &CurrentCorrection = Map[Name];
if (!CurrentCorrection ||
// FIXME: The following should be rolled up into an operator< on
// TypoCorrection with a more principled definition.
@@ -3289,12 +3279,8 @@ void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) {
CurrentCorrection.getAsString(SemaRef.getLangOpts()))
CurrentCorrection = Correction;
- while (BestResults.size() > MaxTypoDistanceResultSets) {
- TypoEditDistanceMap::iterator Last = BestResults.end();
- --Last;
- delete Last->second;
- BestResults.erase(Last);
- }
+ while (BestResults.size() > MaxTypoDistanceResultSets)
+ erase(llvm::prior(BestResults.end()));
}
// Fill the supplied vector with the IdentifierInfo pointers for each piece of
@@ -3882,8 +3868,8 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
while (!Consumer.empty()) {
TypoCorrectionConsumer::distance_iterator DI = Consumer.begin();
unsigned ED = DI->first;
- for (TypoCorrectionConsumer::result_iterator I = DI->second->begin(),
- IEnd = DI->second->end();
+ for (TypoCorrectionConsumer::result_iterator I = DI->second.begin(),
+ IEnd = DI->second.end();
I != IEnd; /* Increment in loop. */) {
// If the item already has been looked up or is a keyword, keep it.
// If a validator callback object was given, drop the correction
@@ -3892,7 +3878,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
TypoCorrectionConsumer::result_iterator Prev = I;
++I;
if (!isCandidateViable(CCC, Prev->second))
- DI->second->erase(Prev);
+ DI->second.erase(Prev);
continue;
}
@@ -3911,7 +3897,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
{
TypoCorrectionConsumer::result_iterator Next = I;
++Next;
- DI->second->erase(I);
+ DI->second.erase(I);
I = Next;
}
break;
@@ -3929,7 +3915,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
I->second.addCorrectionDecl(*TRD);
++I;
if (!isCandidateViable(CCC, Prev->second))
- DI->second->erase(Prev);
+ DI->second.erase(Prev);
break;
}
@@ -3938,14 +3924,14 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
I->second.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>());
++I;
if (!isCandidateViable(CCC, Prev->second))
- DI->second->erase(Prev);
+ DI->second.erase(Prev);
break;
}
}
}
- if (DI->second->empty())
+ if (DI->second.empty())
Consumer.erase(DI);
else if (!getLangOpts().CPlusPlus || QualifiedResults.empty() || !ED)
// If there are results in the closest possible bucket, stop
@@ -4009,7 +3995,7 @@ TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,
// No corrections remain...
if (Consumer.empty()) return TypoCorrection();
- TypoResultsMap &BestResults = *Consumer.begin()->second;
+ TypoResultsMap &BestResults = Consumer.begin()->second;
ED = TypoCorrection::NormalizeEditDistance(Consumer.begin()->first);
if (ED > 0 && Typo->getName().size() / ED < 3) {
@@ -4083,7 +4069,8 @@ std::string TypoCorrection::getAsString(const LangOptions &LO) const {
std::string tmpBuffer;
llvm::raw_string_ostream PrefixOStream(tmpBuffer);
CorrectionNameSpec->print(PrefixOStream, PrintingPolicy(LO));
- return PrefixOStream.str() + CorrectionName.getAsString();
+ CorrectionName.printName(PrefixOStream);
+ return PrefixOStream.str();
}
return CorrectionName.getAsString();
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 284c8de..50230f0 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -11150,6 +11150,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
VK_LValue,
Found.getDecl(),
TemplateArgs);
+ MarkDeclRefReferenced(DRE);
DRE->setHadMultipleCandidates(ULE->getNumDecls() > 1);
return DRE;
}
@@ -11178,6 +11179,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found,
VK_LValue,
Found.getDecl(),
TemplateArgs);
+ MarkDeclRefReferenced(DRE);
DRE->setHadMultipleCandidates(MemExpr->getNumDecls() > 1);
return DRE;
} else {
diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp
index d52c912..0e66329 100644
--- a/lib/Sema/SemaPseudoObject.cpp
+++ b/lib/Sema/SemaPseudoObject.cpp
@@ -214,6 +214,7 @@ namespace {
ObjCMethodDecl *Setter;
Selector SetterSelector;
+ Selector GetterSelector;
public:
ObjCPropertyOpBuilder(Sema &S, ObjCPropertyRefExpr *refExpr) :
@@ -475,8 +476,24 @@ bool ObjCPropertyOpBuilder::findGetter() {
// For implicit properties, just trust the lookup we already did.
if (RefExpr->isImplicitProperty()) {
- Getter = RefExpr->getImplicitPropertyGetter();
- return (Getter != 0);
+ if ((Getter = RefExpr->getImplicitPropertyGetter())) {
+ GetterSelector = Getter->getSelector();
+ return true;
+ }
+ else {
+ // Must build the getter selector the hard way.
+ ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter();
+ assert(setter && "both setter and getter are null - cannot happen");
+ IdentifierInfo *setterName =
+ setter->getSelector().getIdentifierInfoForSlot(0);
+ const char *compStr = setterName->getNameStart();
+ compStr += 3;
+ IdentifierInfo *getterName = &S.Context.Idents.get(compStr);
+ GetterSelector =
+ S.PP.getSelectorTable().getNullarySelector(getterName);
+ return false;
+
+ }
}
ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
@@ -776,7 +793,7 @@ ObjCPropertyOpBuilder::buildIncDecOperation(Scope *Sc, SourceLocation opcLoc,
assert(RefExpr->isImplicitProperty());
S.Diag(opcLoc, diag::err_nogetter_property_incdec)
<< unsigned(UnaryOperator::isDecrementOp(opcode))
- << RefExpr->getImplicitPropertyGetter()->getSelector() // FIXME!
+ << GetterSelector
<< op->getSourceRange();
return ExprError();
}
@@ -1300,6 +1317,11 @@ static Expr *stripOpaqueValuesFromPseudoObjectRef(Sema &S, Expr *E) {
Expr *opaqueRef = E->IgnoreParens();
if (ObjCPropertyRefExpr *refExpr
= dyn_cast<ObjCPropertyRefExpr>(opaqueRef)) {
+ // Class and super property references don't have opaque values in them.
+ if (refExpr->isClassReceiver() || refExpr->isSuperReceiver())
+ return E;
+
+ assert(refExpr->isObjectReceiver() && "Unknown receiver kind?");
OpaqueValueExpr *baseOVE = cast<OpaqueValueExpr>(refExpr->getBase());
return ObjCPropertyRefRebuilder(S, baseOVE->getSourceExpr()).rebuild(E);
} else if (ObjCSubscriptRefExpr *refExpr
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 97c8eb0..9052278 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -345,7 +345,6 @@ Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
StmtResult
Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
SourceLocation ColonLoc, Stmt *SubStmt) {
-
// If the label was multiply defined, reject it now.
if (TheDecl->getStmt()) {
Diag(IdentLoc, diag::err_redefinition_of_label) << TheDecl->getDeclName();
@@ -361,6 +360,16 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl,
return Owned(LS);
}
+StmtResult Sema::ActOnAttributedStmt(SourceLocation AttrLoc,
+ const AttrVec &Attrs,
+ Stmt *SubStmt) {
+ // Fill in the declaration and return it. Variable length will require to
+ // change this to AttributedStmt::Create(Context, ....);
+ // and probably using ArrayRef
+ AttributedStmt *LS = new (Context) AttributedStmt(AttrLoc, Attrs, SubStmt);
+ return Owned(LS);
+}
+
StmtResult
Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, Decl *CondVar,
Stmt *thenStmt, SourceLocation ElseLoc,
diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp
new file mode 100644
index 0000000..21c3297
--- /dev/null
+++ b/lib/Sema/SemaStmtAttr.cpp
@@ -0,0 +1,48 @@
+//===--- SemaStmtAttr.cpp - Statement Attribute Handling ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements stmt-related attribute processing.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+#include "TargetAttributesSema.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "clang/Sema/Lookup.h"
+#include "llvm/ADT/StringExtras.h"
+using namespace clang;
+using namespace sema;
+
+
+static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A) {
+ switch (A.getKind()) {
+ default:
+ // if we're here, then we parsed an attribute, but didn't recognize it as a
+ // statement attribute => it is declaration attribute
+ S.Diag(A.getRange().getBegin(), diag::warn_attribute_invalid_on_stmt) <<
+ A.getName()->getName();
+ return 0;
+ }
+}
+
+StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList,
+ SourceRange Range) {
+ AttrVec Attrs;
+ for (const AttributeList* l = AttrList; l; l = l->getNext()) {
+ if (Attr *a = ProcessStmtAttribute(*this, S, *l))
+ Attrs.push_back(a);
+ }
+
+ if (Attrs.empty())
+ return S;
+
+ return ActOnAttributedStmt(Range.getBegin(), Attrs, S);
+}
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index ff8c4da..51ce2a1 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2496,6 +2496,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
Converted.size(),
SourceRange(TemplateLoc, RAngleLoc));
+ Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
ArgType = SemaRef.SubstType(ArgType, AllTemplateArgs,
Param->getDefaultArgumentLoc(),
Param->getDeclName());
@@ -2544,6 +2545,8 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
Converted.size(),
SourceRange(TemplateLoc, RAngleLoc));
+ Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
return SemaRef.SubstExpr(Param->getDefaultArgument(), AllTemplateArgs);
}
@@ -2591,6 +2594,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
Converted.size(),
SourceRange(TemplateLoc, RAngleLoc));
+ Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
// Substitute into the nested-name-specifier first,
QualifierLoc = Param->getDefaultArgument().getTemplateQualifierLoc();
if (QualifierLoc) {
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 2ea1e6f..d68e464 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -2310,23 +2310,42 @@ Sema::SubstituteExplicitTemplateArguments(
// explicitly-specified template arguments. If the function has a trailing
// return type, substitute it after the arguments to ensure we substitute
// in lexical order.
- if (Proto->hasTrailingReturn() &&
- SubstParmTypes(Function->getLocation(),
- Function->param_begin(), Function->getNumParams(),
- MultiLevelTemplateArgumentList(*ExplicitArgumentList),
- ParamTypes))
- return TDK_SubstitutionFailure;
-
+ if (Proto->hasTrailingReturn()) {
+ if (SubstParmTypes(Function->getLocation(),
+ Function->param_begin(), Function->getNumParams(),
+ MultiLevelTemplateArgumentList(*ExplicitArgumentList),
+ ParamTypes))
+ return TDK_SubstitutionFailure;
+ }
+
// Instantiate the return type.
// FIXME: exception-specifications?
- QualType ResultType
- = SubstType(Proto->getResultType(),
- MultiLevelTemplateArgumentList(*ExplicitArgumentList),
- Function->getTypeSpecStartLoc(),
- Function->getDeclName());
- if (ResultType.isNull() || Trap.hasErrorOccurred())
- return TDK_SubstitutionFailure;
-
+ QualType ResultType;
+ {
+ // C++11 [expr.prim.general]p3:
+ // If a declaration declares a member function or member function
+ // template of a class X, the expression this is a prvalue of type
+ // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
+ // and the end of the function-definition, member-declarator, or
+ // declarator.
+ unsigned ThisTypeQuals = 0;
+ CXXRecordDecl *ThisContext = 0;
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
+ ThisContext = Method->getParent();
+ ThisTypeQuals = Method->getTypeQualifiers();
+ }
+
+ CXXThisScopeRAII ThisScope(*this, ThisContext, ThisTypeQuals,
+ getLangOpts().CPlusPlus0x);
+
+ ResultType = SubstType(Proto->getResultType(),
+ MultiLevelTemplateArgumentList(*ExplicitArgumentList),
+ Function->getTypeSpecStartLoc(),
+ Function->getDeclName());
+ if (ResultType.isNull() || Trap.hasErrorOccurred())
+ return TDK_SubstitutionFailure;
+ }
+
// Instantiate the types of each of the function parameters given the
// explicitly-specified template arguments if we didn't do so earlier.
if (!Proto->hasTrailingReturn() &&
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 4740145..128dc2f 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -153,6 +153,7 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
bool Sema::ActiveTemplateInstantiation::isInstantiationRecord() const {
switch (Kind) {
case TemplateInstantiation:
+ case ExceptionSpecInstantiation:
case DefaultTemplateArgumentInstantiation:
case DefaultFunctionArgumentInstantiation:
return true;
@@ -190,6 +191,29 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
}
}
+Sema::InstantiatingTemplate::
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ FunctionDecl *Entity, ExceptionSpecification,
+ SourceRange InstantiationRange)
+ : SemaRef(SemaRef),
+ SavedInNonInstantiationSFINAEContext(
+ SemaRef.InNonInstantiationSFINAEContext)
+{
+ Invalid = CheckInstantiationDepth(PointOfInstantiation,
+ InstantiationRange);
+ if (!Invalid) {
+ ActiveTemplateInstantiation Inst;
+ Inst.Kind = ActiveTemplateInstantiation::ExceptionSpecInstantiation;
+ Inst.PointOfInstantiation = PointOfInstantiation;
+ Inst.Entity = reinterpret_cast<uintptr_t>(Entity);
+ Inst.TemplateArgs = 0;
+ Inst.NumTemplateArgs = 0;
+ Inst.InstantiationRange = InstantiationRange;
+ SemaRef.InNonInstantiationSFINAEContext = false;
+ SemaRef.ActiveTemplateInstantiations.push_back(Inst);
+ }
+}
+
Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef,
SourceLocation PointOfInstantiation,
TemplateDecl *Template,
@@ -592,6 +616,13 @@ void Sema::PrintInstantiationStack() {
<< Active->InstantiationRange;
break;
}
+
+ case ActiveTemplateInstantiation::ExceptionSpecInstantiation:
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_template_exception_spec_instantiation_here)
+ << cast<FunctionDecl>((Decl *)Active->Entity)
+ << Active->InstantiationRange;
+ break;
}
}
}
@@ -609,6 +640,7 @@ llvm::Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
switch(Active->Kind) {
case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation:
case ActiveTemplateInstantiation::TemplateInstantiation:
+ case ActiveTemplateInstantiation::ExceptionSpecInstantiation:
// This is a template instantiation, so there is no SFINAE.
return llvm::Optional<TemplateDeductionInfo *>();
@@ -789,6 +821,11 @@ namespace {
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL);
+ QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL,
+ CXXRecordDecl *ThisContext,
+ unsigned ThisTypeQuals);
+
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
int indexAdjustment,
llvm::Optional<unsigned> NumExpansions,
@@ -1211,6 +1248,16 @@ QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
return inherited::TransformFunctionProtoType(TLB, TL);
}
+QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL,
+ CXXRecordDecl *ThisContext,
+ unsigned ThisTypeQuals) {
+ // We need a local instantiation scope for this function prototype.
+ LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
+ return inherited::TransformFunctionProtoType(TLB, TL, ThisContext,
+ ThisTypeQuals);
+}
+
ParmVarDecl *
TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm,
int indexAdjustment,
@@ -1446,7 +1493,9 @@ static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) {
TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
const MultiLevelTemplateArgumentList &Args,
SourceLocation Loc,
- DeclarationName Entity) {
+ DeclarationName Entity,
+ CXXRecordDecl *ThisContext,
+ unsigned ThisTypeQuals) {
assert(!ActiveTemplateInstantiations.empty() &&
"Cannot perform an instantiation without some context on the "
"instantiation stack");
@@ -1461,7 +1510,14 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
TypeLoc TL = T->getTypeLoc();
TLB.reserve(TL.getFullDataSize());
- QualType Result = Instantiator.TransformType(TLB, TL);
+ QualType Result;
+
+ if (FunctionProtoTypeLoc *Proto = dyn_cast<FunctionProtoTypeLoc>(&TL)) {
+ Result = Instantiator.TransformFunctionProtoType(TLB, *Proto, ThisContext,
+ ThisTypeQuals);
+ } else {
+ Result = Instantiator.TransformType(TLB, TL);
+ }
if (Result.isNull())
return 0;
@@ -1878,24 +1934,33 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
CheckCompletedCXXClass(Instantiation);
// Attach any in-class member initializers now the class is complete.
- for (unsigned I = 0, N = FieldsWithMemberInitializers.size(); I != N; ++I) {
- FieldDecl *OldField = FieldsWithMemberInitializers[I].first;
- FieldDecl *NewField = FieldsWithMemberInitializers[I].second;
- Expr *OldInit = OldField->getInClassInitializer();
-
- ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs,
- /*CXXDirectInit=*/false);
- if (NewInit.isInvalid())
- NewField->setInvalidDecl();
- else {
- Expr *Init = NewInit.take();
- assert(Init && "no-argument initializer in class");
- assert(!isa<ParenListExpr>(Init) && "call-style init in class");
- ActOnCXXInClassMemberInitializer(NewField,
- Init->getSourceRange().getBegin(), Init);
+ {
+ // C++11 [expr.prim.general]p4:
+ // Otherwise, if a member-declarator declares a non-static data member
+ // (9.2) of a class X, the expression this is a prvalue of type "pointer
+ // to X" within the optional brace-or-equal-initializer. It shall not
+ // appear elsewhere in the member-declarator.
+ CXXThisScopeRAII ThisScope(*this, Instantiation, (unsigned)0);
+
+ for (unsigned I = 0, N = FieldsWithMemberInitializers.size(); I != N; ++I) {
+ FieldDecl *OldField = FieldsWithMemberInitializers[I].first;
+ FieldDecl *NewField = FieldsWithMemberInitializers[I].second;
+ Expr *OldInit = OldField->getInClassInitializer();
+
+ ExprResult NewInit = SubstInitializer(OldInit, TemplateArgs,
+ /*CXXDirectInit=*/false);
+ if (NewInit.isInvalid())
+ NewField->setInvalidDecl();
+ else {
+ Expr *Init = NewInit.take();
+ assert(Init && "no-argument initializer in class");
+ assert(!isa<ParenListExpr>(Init) && "call-style init in class");
+ ActOnCXXInClassMemberInitializer(NewField,
+ Init->getSourceRange().getBegin(),
+ Init);
+ }
}
}
-
// Instantiate late parsed attributes, and attach them to their decls.
// See Sema::InstantiateAttrs
for (LateInstantiatedAttrVec::iterator I = LateAttrs.begin(),
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 8afe7ac..c7bd99c 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2141,10 +2141,19 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
TypeSourceInfo *OldTInfo = D->getTypeSourceInfo();
assert(OldTInfo && "substituting function without type source info");
assert(Params.empty() && "parameter vector is non-empty at start");
+
+ CXXRecordDecl *ThisContext = 0;
+ unsigned ThisTypeQuals = 0;
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+ ThisContext = Method->getParent();
+ ThisTypeQuals = Method->getTypeQualifiers();
+ }
+
TypeSourceInfo *NewTInfo
= SemaRef.SubstFunctionDeclType(OldTInfo, TemplateArgs,
D->getTypeSpecStartLoc(),
- D->getDeclName());
+ D->getDeclName(),
+ ThisContext, ThisTypeQuals);
if (!NewTInfo)
return 0;
@@ -2206,6 +2215,195 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
return NewTInfo;
}
+/// Introduce the instantiated function parameters into the local
+/// instantiation scope, and set the parameter names to those used
+/// in the template.
+static void addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
+ const FunctionDecl *PatternDecl,
+ LocalInstantiationScope &Scope,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ unsigned FParamIdx = 0;
+ for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) {
+ const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I);
+ if (!PatternParam->isParameterPack()) {
+ // Simple case: not a parameter pack.
+ assert(FParamIdx < Function->getNumParams());
+ ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
+ FunctionParam->setDeclName(PatternParam->getDeclName());
+ Scope.InstantiatedLocal(PatternParam, FunctionParam);
+ ++FParamIdx;
+ continue;
+ }
+
+ // Expand the parameter pack.
+ Scope.MakeInstantiatedLocalArgPack(PatternParam);
+ unsigned NumArgumentsInExpansion
+ = S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs);
+ for (unsigned Arg = 0; Arg < NumArgumentsInExpansion; ++Arg) {
+ ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
+ FunctionParam->setDeclName(PatternParam->getDeclName());
+ Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
+ ++FParamIdx;
+ }
+ }
+}
+
+static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
+ const FunctionProtoType *Proto,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ assert(Proto->getExceptionSpecType() != EST_Uninstantiated);
+
+ // C++11 [expr.prim.general]p3:
+ // If a declaration declares a member function or member function
+ // template of a class X, the expression this is a prvalue of type
+ // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
+ // and the end of the function-definition, member-declarator, or
+ // declarator.
+ CXXRecordDecl *ThisContext = 0;
+ unsigned ThisTypeQuals = 0;
+ if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(New)) {
+ ThisContext = Method->getParent();
+ ThisTypeQuals = Method->getTypeQualifiers();
+ }
+ Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, ThisTypeQuals,
+ SemaRef.getLangOpts().CPlusPlus0x);
+
+ // The function has an exception specification or a "noreturn"
+ // attribute. Substitute into each of the exception types.
+ SmallVector<QualType, 4> Exceptions;
+ for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) {
+ // FIXME: Poor location information!
+ if (const PackExpansionType *PackExpansion
+ = Proto->getExceptionType(I)->getAs<PackExpansionType>()) {
+ // We have a pack expansion. Instantiate it.
+ SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),
+ Unexpanded);
+ assert(!Unexpanded.empty() &&
+ "Pack expansion without parameter packs?");
+
+ bool Expand = false;
+ bool RetainExpansion = false;
+ llvm::Optional<unsigned> NumExpansions
+ = PackExpansion->getNumExpansions();
+ if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),
+ SourceRange(),
+ Unexpanded,
+ TemplateArgs,
+ Expand,
+ RetainExpansion,
+ NumExpansions))
+ break;
+
+ if (!Expand) {
+ // We can't expand this pack expansion into separate arguments yet;
+ // just substitute into the pattern and create a new pack expansion
+ // type.
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
+ QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
+ TemplateArgs,
+ New->getLocation(), New->getDeclName());
+ if (T.isNull())
+ break;
+
+ T = SemaRef.Context.getPackExpansionType(T, NumExpansions);
+ Exceptions.push_back(T);
+ continue;
+ }
+
+ // Substitute into the pack expansion pattern for each template
+ bool Invalid = false;
+ for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, ArgIdx);
+
+ QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
+ TemplateArgs,
+ New->getLocation(), New->getDeclName());
+ if (T.isNull()) {
+ Invalid = true;
+ break;
+ }
+
+ Exceptions.push_back(T);
+ }
+
+ if (Invalid)
+ break;
+
+ continue;
+ }
+
+ QualType T
+ = SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs,
+ New->getLocation(), New->getDeclName());
+ if (T.isNull() ||
+ SemaRef.CheckSpecifiedExceptionType(T, New->getLocation()))
+ continue;
+
+ Exceptions.push_back(T);
+ }
+ Expr *NoexceptExpr = 0;
+ if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) {
+ EnterExpressionEvaluationContext Unevaluated(SemaRef,
+ Sema::ConstantEvaluated);
+ ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs);
+ if (E.isUsable())
+ E = SemaRef.CheckBooleanCondition(E.get(), E.get()->getLocStart());
+
+ if (E.isUsable()) {
+ NoexceptExpr = E.take();
+ if (!NoexceptExpr->isTypeDependent() &&
+ !NoexceptExpr->isValueDependent())
+ NoexceptExpr = SemaRef.VerifyIntegerConstantExpression(NoexceptExpr,
+ 0, SemaRef.PDiag(diag::err_noexcept_needs_constant_expression),
+ /*AllowFold*/ false).take();
+ }
+ }
+
+ // Rebuild the function type
+ const FunctionProtoType *NewProto
+ = New->getType()->getAs<FunctionProtoType>();
+ assert(NewProto && "Template instantiation without function prototype?");
+
+ FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
+ EPI.ExceptionSpecType = Proto->getExceptionSpecType();
+ EPI.NumExceptions = Exceptions.size();
+ EPI.Exceptions = Exceptions.data();
+ EPI.NoexceptExpr = NoexceptExpr;
+
+ New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
+ NewProto->arg_type_begin(),
+ NewProto->getNumArgs(),
+ EPI));
+}
+
+void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
+ FunctionDecl *Decl) {
+ const FunctionProtoType *Proto = Decl->getType()->castAs<FunctionProtoType>();
+ if (Proto->getExceptionSpecType() != EST_Uninstantiated)
+ return;
+
+ InstantiatingTemplate Inst(*this, PointOfInstantiation, Decl,
+ InstantiatingTemplate::ExceptionSpecification());
+ if (Inst)
+ return;
+
+ // Enter the scope of this instantiation. We don't use
+ // PushDeclContext because we don't have a scope.
+ Sema::ContextRAII savedContext(*this, Decl);
+ LocalInstantiationScope Scope(*this);
+
+ MultiLevelTemplateArgumentList TemplateArgs =
+ getTemplateInstantiationArgs(Decl, 0, /*RelativeToPrimary*/true);
+
+ FunctionDecl *Template = Proto->getExceptionSpecTemplate();
+ addInstantiatedParametersToScope(*this, Decl, Template, Scope, TemplateArgs);
+
+ ::InstantiateExceptionSpec(*this, Decl,
+ Template->getType()->castAs<FunctionProtoType>(),
+ TemplateArgs);
+}
+
/// \brief Initializes the common fields of an instantiation function
/// declaration (New) from the corresponding fields of its template (Tmpl).
///
@@ -2243,119 +2441,37 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
assert(Proto && "Function template without prototype?");
if (Proto->hasExceptionSpec() || Proto->getNoReturnAttr()) {
- // The function has an exception specification or a "noreturn"
- // attribute. Substitute into each of the exception types.
- SmallVector<QualType, 4> Exceptions;
- for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) {
- // FIXME: Poor location information!
- if (const PackExpansionType *PackExpansion
- = Proto->getExceptionType(I)->getAs<PackExpansionType>()) {
- // We have a pack expansion. Instantiate it.
- SmallVector<UnexpandedParameterPack, 2> Unexpanded;
- SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),
- Unexpanded);
- assert(!Unexpanded.empty() &&
- "Pack expansion without parameter packs?");
-
- bool Expand = false;
- bool RetainExpansion = false;
- llvm::Optional<unsigned> NumExpansions
- = PackExpansion->getNumExpansions();
- if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),
- SourceRange(),
- Unexpanded,
- TemplateArgs,
- Expand,
- RetainExpansion,
- NumExpansions))
- break;
-
- if (!Expand) {
- // We can't expand this pack expansion into separate arguments yet;
- // just substitute into the pattern and create a new pack expansion
- // type.
- Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
- QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
- TemplateArgs,
- New->getLocation(), New->getDeclName());
- if (T.isNull())
- break;
-
- T = SemaRef.Context.getPackExpansionType(T, NumExpansions);
- Exceptions.push_back(T);
- continue;
- }
-
- // Substitute into the pack expansion pattern for each template
- bool Invalid = false;
- for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {
- Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, ArgIdx);
-
- QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
- TemplateArgs,
- New->getLocation(), New->getDeclName());
- if (T.isNull()) {
- Invalid = true;
- break;
- }
-
- Exceptions.push_back(T);
- }
-
- if (Invalid)
- break;
-
- continue;
- }
-
- QualType T
- = SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs,
- New->getLocation(), New->getDeclName());
- if (T.isNull() ||
- SemaRef.CheckSpecifiedExceptionType(T, New->getLocation()))
- continue;
-
- Exceptions.push_back(T);
- }
- Expr *NoexceptExpr = 0;
- if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) {
- EnterExpressionEvaluationContext Unevaluated(SemaRef,
- Sema::ConstantEvaluated);
- ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs);
- if (E.isUsable())
- E = SemaRef.CheckBooleanCondition(E.get(), E.get()->getLocStart());
-
- if (E.isUsable()) {
- NoexceptExpr = E.take();
- if (!NoexceptExpr->isTypeDependent() &&
- !NoexceptExpr->isValueDependent())
- NoexceptExpr = SemaRef.VerifyIntegerConstantExpression(NoexceptExpr,
- 0, SemaRef.PDiag(diag::err_noexcept_needs_constant_expression),
- /*AllowFold*/ false).take();
- }
- }
-
- // Rebuild the function type
-
FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
- EPI.ExceptionSpecType = Proto->getExceptionSpecType();
- EPI.NumExceptions = Exceptions.size();
- EPI.Exceptions = Exceptions.data();
- EPI.NoexceptExpr = NoexceptExpr;
- EPI.ExtInfo = Proto->getExtInfo();
- const FunctionProtoType *NewProto
- = New->getType()->getAs<FunctionProtoType>();
- assert(NewProto && "Template instantiation without function prototype?");
- New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
- NewProto->arg_type_begin(),
- NewProto->getNumArgs(),
- EPI));
+ // DR1330: In C++11, defer instantiation of a non-trivial
+ // exception specification.
+ if (SemaRef.getLangOpts().CPlusPlus0x &&
+ EPI.ExceptionSpecType != EST_None &&
+ EPI.ExceptionSpecType != EST_DynamicNone &&
+ EPI.ExceptionSpecType != EST_BasicNoexcept) {
+ FunctionDecl *ExceptionSpecTemplate = Tmpl;
+ if (EPI.ExceptionSpecType == EST_Uninstantiated)
+ ExceptionSpecTemplate = EPI.ExceptionSpecTemplate;
+
+ // Mark the function has having an uninstantiated exception specification.
+ const FunctionProtoType *NewProto
+ = New->getType()->getAs<FunctionProtoType>();
+ assert(NewProto && "Template instantiation without function prototype?");
+ EPI = NewProto->getExtProtoInfo();
+ EPI.ExceptionSpecType = EST_Uninstantiated;
+ EPI.ExceptionSpecDecl = New;
+ EPI.ExceptionSpecTemplate = ExceptionSpecTemplate;
+ New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(),
+ NewProto->arg_type_begin(),
+ NewProto->getNumArgs(),
+ EPI));
+ } else {
+ ::InstantiateExceptionSpec(SemaRef, New, Proto, TemplateArgs);
+ }
}
- const FunctionDecl* Definition = Tmpl;
-
// Get the definition. Leaves the variable unchanged if undefined.
+ const FunctionDecl *Definition = Tmpl;
Tmpl->isDefined(Definition);
SemaRef.InstantiateAttrs(TemplateArgs, Definition, New,
@@ -2513,33 +2629,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
MultiLevelTemplateArgumentList TemplateArgs =
getTemplateInstantiationArgs(Function, 0, false, PatternDecl);
- // Introduce the instantiated function parameters into the local
- // instantiation scope, and set the parameter names to those used
- // in the template.
- unsigned FParamIdx = 0;
- for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) {
- const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I);
- if (!PatternParam->isParameterPack()) {
- // Simple case: not a parameter pack.
- assert(FParamIdx < Function->getNumParams());
- ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
- FunctionParam->setDeclName(PatternParam->getDeclName());
- Scope.InstantiatedLocal(PatternParam, FunctionParam);
- ++FParamIdx;
- continue;
- }
-
- // Expand the parameter pack.
- Scope.MakeInstantiatedLocalArgPack(PatternParam);
- unsigned NumArgumentsInExpansion
- = getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs);
- for (unsigned Arg = 0; Arg < NumArgumentsInExpansion; ++Arg) {
- ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
- FunctionParam->setDeclName(PatternParam->getDeclName());
- Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
- ++FParamIdx;
- }
- }
+ addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope,
+ TemplateArgs);
if (PatternDecl->isDefaulted()) {
ActOnFinishFunctionBody(Function, 0, /*IsInstantiation=*/true);
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index c41df82..d0906de 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -561,7 +561,7 @@ static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
/*const qualifier*/SourceLocation(),
/*volatile qualifier*/SourceLocation(),
/*mutable qualifier*/SourceLocation(),
- /*EH*/ EST_None, SourceLocation(), 0, 0, 0, 0,
+ /*EH*/ EST_None, SourceLocation(), 0, 0, 0, 0, 0,
/*parens*/ loc, loc,
declarator));
@@ -2371,34 +2371,33 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
EPI.ConsumedArguments = ConsumedArguments.data();
SmallVector<QualType, 4> Exceptions;
- EPI.ExceptionSpecType = FTI.getExceptionSpecType();
+ SmallVector<ParsedType, 2> DynamicExceptions;
+ SmallVector<SourceRange, 2> DynamicExceptionRanges;
+ Expr *NoexceptExpr = 0;
+
if (FTI.getExceptionSpecType() == EST_Dynamic) {
- Exceptions.reserve(FTI.NumExceptions);
- for (unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) {
- // FIXME: Preserve type source info.
- QualType ET = S.GetTypeFromParser(FTI.Exceptions[ei].Ty);
- // Check that the type is valid for an exception spec, and
- // drop it if not.
- if (!S.CheckSpecifiedExceptionType(ET, FTI.Exceptions[ei].Range))
- Exceptions.push_back(ET);
+ // FIXME: It's rather inefficient to have to split into two vectors
+ // here.
+ unsigned N = FTI.NumExceptions;
+ DynamicExceptions.reserve(N);
+ DynamicExceptionRanges.reserve(N);
+ for (unsigned I = 0; I != N; ++I) {
+ DynamicExceptions.push_back(FTI.Exceptions[I].Ty);
+ DynamicExceptionRanges.push_back(FTI.Exceptions[I].Range);
}
- EPI.NumExceptions = Exceptions.size();
- EPI.Exceptions = Exceptions.data();
} else if (FTI.getExceptionSpecType() == EST_ComputedNoexcept) {
- // If an error occurred, there's no expression here.
- if (Expr *NoexceptExpr = FTI.NoexceptExpr) {
- assert((NoexceptExpr->isTypeDependent() ||
- NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==
- Context.BoolTy) &&
- "Parser should have made sure that the expression is boolean");
- if (!NoexceptExpr->isValueDependent())
- NoexceptExpr = S.VerifyIntegerConstantExpression(NoexceptExpr, 0,
- S.PDiag(diag::err_noexcept_needs_constant_expression),
- /*AllowFold*/ false).take();
- EPI.NoexceptExpr = NoexceptExpr;
- }
- } else if (FTI.getExceptionSpecType() == EST_None &&
- ImplicitlyNoexcept && chunkIndex == 0) {
+ NoexceptExpr = FTI.NoexceptExpr;
+ }
+
+ S.checkExceptionSpecification(FTI.getExceptionSpecType(),
+ DynamicExceptions,
+ DynamicExceptionRanges,
+ NoexceptExpr,
+ Exceptions,
+ EPI);
+
+ if (FTI.getExceptionSpecType() == EST_None &&
+ ImplicitlyNoexcept && chunkIndex == 0) {
// Only the outermost chunk is marked noexcept, of course.
EPI.ExceptionSpecType = EST_BasicNoexcept;
}
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index fdb861e..a66378e 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -522,6 +522,11 @@ public:
QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T);
#include "clang/AST/TypeLocNodes.def"
+ QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL,
+ CXXRecordDecl *ThisContext,
+ unsigned ThisTypeQuals);
+
StmtResult
TransformSEHHandler(Stmt *Handler);
@@ -1044,6 +1049,15 @@ public:
return SemaRef.ActOnLabelStmt(IdentLoc, L, ColonLoc, SubStmt);
}
+ /// \brief Build a new label statement.
+ ///
+ /// By default, performs semantic analysis to build the new statement.
+ /// Subclasses may override this routine to provide different behavior.
+ StmtResult RebuildAttributedStmt(SourceLocation AttrLoc, const AttrVec &Attrs,
+ Stmt *SubStmt) {
+ return SemaRef.ActOnAttributedStmt(AttrLoc, Attrs, SubStmt);
+ }
+
/// \brief Build a new "if" statement.
///
/// By default, performs semantic analysis to build the new statement.
@@ -4156,12 +4170,18 @@ template<typename Derived>
QualType
TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL) {
+ return getDerived().TransformFunctionProtoType(TLB, TL, 0, 0);
+}
+
+template<typename Derived>
+QualType
+TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
+ FunctionProtoTypeLoc TL,
+ CXXRecordDecl *ThisContext,
+ unsigned ThisTypeQuals) {
// Transform the parameters and return type.
//
- // We instantiate in source order, with the return type first followed by
- // the parameters, because users tend to expect this (even if they shouldn't
- // rely on it!).
- //
+ // We are required to instantiate the params and return type in source order.
// When the function has a trailing return type, we instantiate the
// parameters before the return type, since the return type can then refer
// to the parameters themselves (via decltype, sizeof, etc.).
@@ -4180,9 +4200,19 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
ParamTypes, &ParamDecls))
return QualType();
- ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
- if (ResultType.isNull())
- return QualType();
+ {
+ // C++11 [expr.prim.general]p3:
+ // If a declaration declares a member function or member function
+ // template of a class X, the expression this is a prvalue of type
+ // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
+ // and the end of the function-definition, member-declarator, or
+ // declarator.
+ Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, ThisTypeQuals);
+
+ ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
+ if (ResultType.isNull())
+ return QualType();
+ }
}
else {
ResultType = getDerived().TransformType(TLB, TL.getResultLoc());
@@ -4197,6 +4227,8 @@ TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB,
return QualType();
}
+ // FIXME: Need to transform the exception-specification too.
+
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() ||
ResultType != T->getResultType() ||
@@ -5154,8 +5186,8 @@ TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) {
S->getDecl());
if (!LD)
return StmtError();
-
-
+
+
// FIXME: Pass the real colon location in.
return getDerived().RebuildLabelStmt(S->getIdentLoc(),
cast<LabelDecl>(LD), SourceLocation(),
@@ -5164,6 +5196,22 @@ TreeTransform<Derived>::TransformLabelStmt(LabelStmt *S) {
template<typename Derived>
StmtResult
+TreeTransform<Derived>::TransformAttributedStmt(AttributedStmt *S) {
+ StmtResult SubStmt = getDerived().TransformStmt(S->getSubStmt());
+ if (SubStmt.isInvalid())
+ return StmtError();
+
+ // TODO: transform attributes
+ if (SubStmt.get() == S->getSubStmt() /* && attrs are the same */)
+ return S;
+
+ return getDerived().RebuildAttributedStmt(S->getAttrLoc(),
+ S->getAttrs(),
+ SubStmt.get());
+}
+
+template<typename Derived>
+StmtResult
TreeTransform<Derived>::TransformIfStmt(IfStmt *S) {
// Transform the condition
ExprResult Cond;
OpenPOWER on IntegriCloud