summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2015-03-03 01:50:05 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2015-03-03 01:50:05 +0000
commitd09a51c299ab277119b2e96b26ed9864c6404ebe (patch)
treeea05b065457d4b843e712b0964d957df7914a85c /clang
parent786ad180496d20cf224ba30b25a754cc2d934b2b (diff)
downloadbcm5719-llvm-d09a51c299ab277119b2e96b26ed9864c6404ebe.tar.gz
bcm5719-llvm-d09a51c299ab277119b2e96b26ed9864c6404ebe.zip
Sema: Properly initialize the thrown exception object
We would create the exception object with the wrong qualifiers, ensuring that the wrong copy constructor would get called. llvm-svn: 231049
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/AST/ASTContext.h2
-rw-r--r--clang/lib/AST/ASTContext.cpp13
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp27
-rw-r--r--clang/test/SemaCXX/exceptions.cpp13
4 files changed, 34 insertions, 21 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 0bc0330882e..9b22aa4a83f 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1936,6 +1936,8 @@ public:
/// cv-qualifiers.
QualType getSignatureParameterType(QualType T) const;
+ QualType getExceptionObjectType(QualType T) const;
+
/// \brief Return the properly qualified result of decaying the specified
/// array type to a pointer.
///
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 8a99162c1cf..fc40f7e8e23 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -4338,6 +4338,19 @@ QualType ASTContext::getSignatureParameterType(QualType T) const {
return T.getUnqualifiedType();
}
+QualType ASTContext::getExceptionObjectType(QualType T) const {
+ // C++ [except.throw]p3:
+ // A throw-expression initializes a temporary object, called the exception
+ // object, the type of which is determined by removing any top-level
+ // cv-qualifiers from the static type of the operand of throw and adjusting
+ // the type from "array of T" or "function returning T" to "pointer to T"
+ // or "pointer to function returning T", [...]
+ T = getVariableArrayDecayedType(T);
+ if (T->isArrayType() || T->isFunctionType())
+ T = getDecayedType(T);
+ return T.getUnqualifiedType();
+}
+
/// getArrayDecayedType - Return the properly qualified result of decaying the
/// specified array type to a pointer. This operation is non-trivial when
/// handling typedefs etc. The canonical type of "T" must be an array type,
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 695c3db1461..6ad0b24275a 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -660,24 +660,10 @@ ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex,
/// CheckCXXThrowOperand - Validate the operand of a throw.
ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
bool IsThrownVarInScope) {
- // C++ [except.throw]p3:
- // A throw-expression initializes a temporary object, called the exception
- // object, the type of which is determined by removing any top-level
- // cv-qualifiers from the static type of the operand of throw and adjusting
- // the type from "array of T" or "function returning T" to "pointer to T"
- // or "pointer to function returning T", [...]
- if (E->getType().hasQualifiers())
- E = ImpCastExprToType(E, E->getType().getUnqualifiedType(), CK_NoOp,
- E->getValueKind()).get();
-
- ExprResult Res = DefaultFunctionArrayConversion(E);
- if (Res.isInvalid())
- return ExprError();
- E = Res.get();
-
+ QualType ExceptionObjectTy = Context.getExceptionObjectType(E->getType());
// If the type of the exception would be an incomplete type or a pointer
// to an incomplete type other than (cv) void the program is ill-formed.
- QualType Ty = E->getType();
+ QualType Ty = ExceptionObjectTy;
bool isPointer = false;
if (const PointerType* Ptr = Ty->getAs<PointerType>()) {
Ty = Ptr->getPointeeType();
@@ -690,7 +676,7 @@ ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
E->getSourceRange()))
return ExprError();
- if (RequireNonAbstractType(ThrowLoc, E->getType(),
+ if (RequireNonAbstractType(ThrowLoc, ExceptionObjectTy,
diag::err_throw_abstract_type, E))
return ExprError();
}
@@ -714,11 +700,10 @@ ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E,
NRVOVariable = getCopyElisionCandidate(QualType(), E, false);
InitializedEntity Entity =
- InitializedEntity::InitializeException(ThrowLoc, E->getType(),
+ InitializedEntity::InitializeException(ThrowLoc, ExceptionObjectTy,
/*NRVO=*/NRVOVariable != nullptr);
- Res = PerformMoveOrCopyInitialization(Entity, NRVOVariable,
- QualType(), E,
- IsThrownVarInScope);
+ ExprResult Res = PerformMoveOrCopyInitialization(
+ Entity, NRVOVariable, QualType(), E, IsThrownVarInScope);
if (Res.isInvalid())
return ExprError();
E = Res.get();
diff --git a/clang/test/SemaCXX/exceptions.cpp b/clang/test/SemaCXX/exceptions.cpp
index 9646a9c3b31..5f4ff23eb77 100644
--- a/clang/test/SemaCXX/exceptions.cpp
+++ b/clang/test/SemaCXX/exceptions.cpp
@@ -145,3 +145,16 @@ namespace Decay {
}
void rval_ref() throw (int &&); // expected-error {{rvalue reference type 'int &&' is not allowed in exception specification}} expected-warning {{C++11}}
+
+namespace ConstVolatile {
+struct S {
+ S() {} // expected-note{{candidate constructor not viable}}
+ S(const S &s); // expected-note{{candidate constructor not viable}}
+};
+
+typedef const volatile S CVS;
+
+void f() {
+ throw CVS(); // expected-error{{no matching constructor for initialization}}
+}
+}
OpenPOWER on IntegriCloud