summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-04-17 00:58:00 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-04-17 00:58:00 +0000
commite6975e9b0985ad7f7ff9187e38d95bfe9ac4181b (patch)
treec68d347ef93340e9e17ee01fc56755561260b697 /include
parent7fea7c81c0970cdb150c1fadb2776dec9fd09780 (diff)
Implement DR1330 in C++11 mode, to support libstdc++4.7 which uses it.
We have a new flavor of exception specification, EST_Uninstantiated. A function type with this exception specification carries a pointer to a FunctionDecl, and the exception specification for that FunctionDecl is instantiated (if needed) and used in the place of the function type's exception specification. When a function template declaration with a non-trivial exception specification is instantiated, the specialization's exception specification is set to this new 'uninstantiated' kind rather than being instantiated immediately. Expr::CanThrow has migrated onto Sema, so it can instantiate exception specs on-demand. Also, any odr-use of a function triggers the instantiation of its exception specification (the exception specification could be needed by IRGen). In passing, fix two places where a DeclRefExpr was created but the corresponding function was not actually marked odr-used. We used to get away with this, but don't any more. Also fix a bug where instantiating an exception specification which refers to function parameters resulted in a crash. We still have the same bug in default arguments, which I'll be looking into next. This, plus a tiny patch to fix libstdc++'s common_type, is enough for clang to parse (and, in very limited testing, support) all of libstdc++4.7's standard headers. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154886 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r--include/clang/AST/Expr.h10
-rw-r--r--include/clang/AST/Type.h18
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--include/clang/Basic/ExceptionSpecificationType.h18
-rw-r--r--include/clang/Sema/Sema.h29
5 files changed, 57 insertions, 20 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index a7822fab1c..b0b9b0fd6f 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -581,16 +581,6 @@ public:
/// member expression.
static QualType findBoundMemberType(const Expr *expr);
- /// \brief Result type of CanThrow().
- enum CanThrowResult {
- CT_Cannot,
- CT_Dependent,
- CT_Can
- };
- /// \brief Test if this expression, if evaluated, might throw, according to
- /// the rules of C++ [expr.unary.noexcept].
- CanThrowResult CanThrow(ASTContext &C) const;
-
/// IgnoreImpCasts - Skip past any implicit casts which might
/// surround this expression. Only skips ImplicitCastExprs.
Expr *IgnoreImpCasts() LLVM_READONLY;
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 7bd367c054..9fd4901672 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -79,6 +79,7 @@ namespace clang {
class CXXRecordDecl;
class EnumDecl;
class FieldDecl;
+ class FunctionDecl;
class ObjCInterfaceDecl;
class ObjCProtocolDecl;
class ObjCMethodDecl;
@@ -2700,7 +2701,8 @@ public:
ExtProtoInfo() :
Variadic(false), HasTrailingReturn(false), TypeQuals(0),
ExceptionSpecType(EST_None), RefQualifier(RQ_None),
- NumExceptions(0), Exceptions(0), NoexceptExpr(0), ConsumedArguments(0) {}
+ NumExceptions(0), Exceptions(0), NoexceptExpr(0), ExceptionSpecDecl(0),
+ ConsumedArguments(0) {}
FunctionType::ExtInfo ExtInfo;
bool Variadic : 1;
@@ -2711,6 +2713,7 @@ public:
unsigned NumExceptions;
const QualType *Exceptions;
Expr *NoexceptExpr;
+ FunctionDecl *ExceptionSpecDecl;
const bool *ConsumedArguments;
};
@@ -2756,6 +2759,10 @@ private:
// NoexceptExpr - Instead of Exceptions, there may be a single Expr* pointing
// to the expression in the noexcept() specifier.
+ // ExceptionSpecDecl - Instead of Exceptions, there may be a single
+ // FunctionDecl* pointing to the function which should be used to resolve
+ // this function type's exception specification.
+
// ConsumedArgs - A variable size array, following Exceptions
// and of length NumArgs, holding flags indicating which arguments
// are consumed. This only appears if HasAnyConsumedArgs is true.
@@ -2795,6 +2802,8 @@ public:
EPI.Exceptions = exception_begin();
} else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
EPI.NoexceptExpr = getNoexceptExpr();
+ } else if (EPI.ExceptionSpecType == EST_Uninstantiated) {
+ EPI.ExceptionSpecDecl = getExceptionSpecDecl();
}
if (hasAnyConsumedArgs())
EPI.ConsumedArguments = getConsumedArgsBuffer();
@@ -2838,9 +2847,14 @@ public:
// NoexceptExpr sits where the arguments end.
return *reinterpret_cast<Expr *const *>(arg_type_end());
}
+ FunctionDecl *getExceptionSpecDecl() const {
+ if (getExceptionSpecType() != EST_Uninstantiated)
+ return 0;
+ return *reinterpret_cast<FunctionDecl * const *>(arg_type_end());
+ }
bool isNothrow(ASTContext &Ctx) const {
ExceptionSpecificationType EST = getExceptionSpecType();
- assert(EST != EST_Delayed);
+ assert(EST != EST_Delayed && EST != EST_Uninstantiated);
if (EST == EST_DynamicNone || EST == EST_BasicNoexcept)
return true;
if (EST != EST_ComputedNoexcept)
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index baaddcfeb2..779af403a6 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2583,6 +2583,8 @@ def note_template_enum_def_here : Note<
"in instantiation of enumeration %q0 requested here">;
def note_template_type_alias_instantiation_here : Note<
"in instantiation of template type alias %0 requested here">;
+def note_template_exception_spec_instantiation_here : Note<
+ "in instantiation of exception specification for %0 requested here">;
def note_default_arg_instantiation_here : Note<
"in instantiation of default argument for '%0' required here">;
diff --git a/include/clang/Basic/ExceptionSpecificationType.h b/include/clang/Basic/ExceptionSpecificationType.h
index 98cfd297ad..e911bde191 100644
--- a/include/clang/Basic/ExceptionSpecificationType.h
+++ b/include/clang/Basic/ExceptionSpecificationType.h
@@ -16,7 +16,7 @@
namespace clang {
-/// \brief The various types of exception specifications that exist in C++0x.
+/// \brief The various types of exception specifications that exist in C++11.
enum ExceptionSpecificationType {
EST_None, ///< no exception specification
EST_DynamicNone, ///< throw()
@@ -24,7 +24,8 @@ enum ExceptionSpecificationType {
EST_MSAny, ///< Microsoft throw(...) extension
EST_BasicNoexcept, ///< noexcept
EST_ComputedNoexcept, ///< noexcept(expression)
- EST_Delayed ///< not known yet
+ EST_Delayed, ///< not known yet
+ EST_Uninstantiated ///< not instantiated yet
};
inline bool isDynamicExceptionSpec(ExceptionSpecificationType ESpecType) {
@@ -35,6 +36,19 @@ inline bool isNoexceptExceptionSpec(ExceptionSpecificationType ESpecType) {
return ESpecType == EST_BasicNoexcept || ESpecType == EST_ComputedNoexcept;
}
+/// \brief Possible results from evaluation of a noexcept expression.
+enum CanThrowResult {
+ CT_Cannot,
+ CT_Dependent,
+ CT_Can
+};
+
+inline CanThrowResult mergeCanThrow(CanThrowResult CT1, CanThrowResult CT2) {
+ // CanThrowResult constants are ordered so that the maximum is the correct
+ // merge result.
+ return CT1 > CT2 ? CT1 : CT2;
+}
+
} // end namespace clang
#endif // LLVM_CLANG_BASIC_EXCEPTIONSPECIFICATIONTYPE_H
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 7de59e0f5d..c845ee5549 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -907,6 +907,9 @@ public:
DeclarationNameInfo GetNameForDeclarator(Declarator &D);
DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name);
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo = 0);
+ CanThrowResult canThrow(const Expr *E);
+ const FunctionProtoType *ResolveExceptionSpec(SourceLocation Loc,
+ const FunctionProtoType *FPT);
bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range);
bool CheckDistantExceptionSpec(QualType T);
bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New);
@@ -3050,7 +3053,7 @@ public:
/// implicitly-declared special member functions.
class ImplicitExceptionSpecification {
// Pointer to allow copying
- ASTContext *Context;
+ Sema *Self;
// We order exception specifications thus:
// noexcept is the most restrictive, but is only used in C++0x.
// throw() comes next.
@@ -3074,9 +3077,9 @@ public:
}
public:
- explicit ImplicitExceptionSpecification(ASTContext &Context)
- : Context(&Context), ComputedEST(EST_BasicNoexcept) {
- if (!Context.getLangOpts().CPlusPlus0x)
+ explicit ImplicitExceptionSpecification(Sema &Self)
+ : Self(&Self), ComputedEST(EST_BasicNoexcept) {
+ if (!Self.Context.getLangOpts().CPlusPlus0x)
ComputedEST = EST_DynamicNone;
}
@@ -3094,7 +3097,7 @@ public:
const QualType *data() const { return Exceptions.data(); }
/// \brief Integrate another called method into the collected data.
- void CalledDecl(CXXMethodDecl *Method);
+ void CalledDecl(SourceLocation CallLoc, CXXMethodDecl *Method);
/// \brief Integrate an invoked expression into the collected data.
void CalledExpr(Expr *E);
@@ -5194,7 +5197,11 @@ public:
/// We are checking the validity of a default template argument that
/// has been used when naming a template-id.
- DefaultTemplateArgumentChecking
+ DefaultTemplateArgumentChecking,
+
+ /// We are instantiating the exception specification for a function
+ /// template which was deferred until it was needed.
+ ExceptionSpecInstantiation
} Kind;
/// \brief The point of instantiation within the source code.
@@ -5242,6 +5249,7 @@ public:
switch (X.Kind) {
case TemplateInstantiation:
+ case ExceptionSpecInstantiation:
return true;
case PriorTemplateArgumentSubstitution:
@@ -5359,6 +5367,13 @@ public:
Decl *Entity,
SourceRange InstantiationRange = SourceRange());
+ struct ExceptionSpecification {};
+ /// \brief Note that we are instantiating an exception specification
+ /// of a function template.
+ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+ FunctionDecl *Entity, ExceptionSpecification,
+ SourceRange InstantiationRange = SourceRange());
+
/// \brief Note that we are instantiating a default argument in a
/// template-id.
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
@@ -5658,6 +5673,8 @@ public:
TemplateArgumentListInfo &Result,
const MultiLevelTemplateArgumentList &TemplateArgs);
+ void InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
+ FunctionDecl *Function);
void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
FunctionDecl *Function,
bool Recursive = false,