aboutsummaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang')
-rw-r--r--include/clang/AST/Expr.h112
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h16
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td7
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td15
-rw-r--r--include/clang/Basic/StmtNodes.td1
-rw-r--r--include/clang/Basic/TokenKinds.def1
-rw-r--r--include/clang/Parse/Parser.h2
-rw-r--r--include/clang/Sema/Ownership.h13
-rw-r--r--include/clang/Sema/Sema.h14
-rw-r--r--include/clang/Serialization/ASTBitCodes.h2
10 files changed, 178 insertions, 5 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index ef677610e6..9de01af64f 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -3679,6 +3679,118 @@ public:
};
+/// \brief Represents a C1X generic selection.
+///
+/// A generic selection (C1X 6.5.1.1) contains an unevaluated controlling
+/// expression, followed by one or more generic associations. Each generic
+/// association specifies a type name and an expression, or "default" and an
+/// expression (in which case it is known as a default generic association).
+/// The type and value of the generic selection are identical to those of its
+/// result expression, which is defined as the expression in the generic
+/// association with a type name that is compatible with the type of the
+/// controlling expression, or the expression in the default generic association
+/// if no types are compatible. For example:
+///
+/// @code
+/// _Generic(X, double: 1, float: 2, default: 3)
+/// @endcode
+///
+/// The above expression evaluates to 1 if 1.0 is substituted for X, 2 if 1.0f
+/// or 3 if "hello".
+///
+/// As an extension, generic selections are allowed in C++, where the following
+/// additional semantics apply:
+///
+/// Any generic selection whose controlling expression is type-dependent or
+/// which names a dependent type in its association list is result-dependent,
+/// which means that the choice of result expression is dependent.
+/// Result-dependent generic associations are both type- and value-dependent.
+class GenericSelectionExpr : public Expr {
+ enum { CONTROLLING, END_EXPR };
+ TypeSourceInfo **AssocTypes;
+ Stmt **SubExprs;
+ unsigned NumAssocs, ResultIndex;
+ SourceLocation GenericLoc, DefaultLoc, RParenLoc;
+
+public:
+ GenericSelectionExpr(ASTContext &Context,
+ SourceLocation GenericLoc, Expr *ControllingExpr,
+ TypeSourceInfo **AssocTypes, Expr **AssocExprs,
+ unsigned NumAssocs, SourceLocation DefaultLoc,
+ SourceLocation RParenLoc,
+ bool ContainsUnexpandedParameterPack,
+ unsigned ResultIndex);
+
+ /// This constructor is used in the result-dependent case.
+ GenericSelectionExpr(ASTContext &Context,
+ SourceLocation GenericLoc, Expr *ControllingExpr,
+ TypeSourceInfo **AssocTypes, Expr **AssocExprs,
+ unsigned NumAssocs, SourceLocation DefaultLoc,
+ SourceLocation RParenLoc,
+ bool ContainsUnexpandedParameterPack);
+
+ explicit GenericSelectionExpr(EmptyShell Empty)
+ : Expr(GenericSelectionExprClass, Empty) { }
+
+ unsigned getNumAssocs() const { return NumAssocs; }
+
+ SourceLocation getGenericLoc() const { return GenericLoc; }
+ SourceLocation getDefaultLoc() const { return DefaultLoc; }
+ SourceLocation getRParenLoc() const { return RParenLoc; }
+
+ const Expr *getAssocExpr(unsigned i) const {
+ return cast<Expr>(SubExprs[END_EXPR+i]);
+ }
+ Expr *getAssocExpr(unsigned i) { return cast<Expr>(SubExprs[END_EXPR+i]); }
+
+ const TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) const {
+ return AssocTypes[i];
+ }
+ TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) { return AssocTypes[i]; }
+
+ QualType getAssocType(unsigned i) const {
+ if (const TypeSourceInfo *TS = getAssocTypeSourceInfo(i))
+ return TS->getType();
+ else
+ return QualType();
+ }
+
+ const Expr *getControllingExpr() const {
+ return cast<Expr>(SubExprs[CONTROLLING]);
+ }
+ Expr *getControllingExpr() { return cast<Expr>(SubExprs[CONTROLLING]); }
+
+ /// Whether this generic selection is result-dependent.
+ bool isResultDependent() const { return ResultIndex == -1U; }
+
+ /// The zero-based index of the result expression's generic association in
+ /// the generic selection's association list. Defined only if the
+ /// generic selection is not result-dependent.
+ unsigned getResultIndex() const {
+ assert(!isResultDependent() && "Generic selection is result-dependent");
+ return ResultIndex;
+ }
+
+ /// The generic selection's result expression. Defined only if the
+ /// generic selection is not result-dependent.
+ const Expr *getResultExpr() const { return getAssocExpr(getResultIndex()); }
+ Expr *getResultExpr() { return getAssocExpr(getResultIndex()); }
+
+ SourceRange getSourceRange() const {
+ return SourceRange(GenericLoc, RParenLoc);
+ }
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == GenericSelectionExprClass;
+ }
+ static bool classof(const GenericSelectionExpr *) { return true; }
+
+ child_range children() {
+ return child_range(SubExprs, SubExprs+END_EXPR+NumAssocs);
+ }
+
+ friend class ASTStmtReader;
+};
+
//===----------------------------------------------------------------------===//
// Clang Extensions
//===----------------------------------------------------------------------===//
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index 2a4348feac..d4a90fbefd 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -1777,6 +1777,22 @@ bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) {
return true;
}
+// GenericSelectionExpr is a special case because the types and expressions
+// are interleaved. We also need to watch out for null types (default
+// generic associations).
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::
+TraverseGenericSelectionExpr(GenericSelectionExpr *S) {
+ TRY_TO(WalkUpFromGenericSelectionExpr(S));
+ TRY_TO(TraverseStmt(S->getControllingExpr()));
+ for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
+ if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i))
+ TRY_TO(TraverseTypeLoc(TS->getTypeLoc()));
+ TRY_TO(TraverseStmt(S->getAssocExpr(i)));
+ }
+ return true;
+}
+
DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, {
// This is called for code like 'return T()' where T is a built-in
// (i.e. non-class) type.
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 7baceb50bd..03067e845c 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -67,6 +67,13 @@ def ext_ms_enum_fixed_underlying_type : Extension<
"enumeration types with a fixed underlying type are a Microsoft extension">,
InGroup<Microsoft>;
+def ext_c1x_generic_selection : Extension<
+ "generic selections are a C1X-specific feature">;
+def err_duplicate_default_assoc : Error<
+ "duplicate default generic association">;
+def note_previous_default_assoc : Note<
+ "previous default generic association is here">;
+
def ext_gnu_indirect_goto : Extension<
"use of GNU indirect-goto extension">, InGroup<GNU>;
def ext_gnu_address_of_label : Extension<
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index b96c461c6c..bddfff2f6e 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3646,6 +3646,21 @@ def warn_stringcompare : Warning<
"result of comparison against %select{a string literal|@encode}0 is "
"unspecified (use strncmp instead)">;
+// Generic selections.
+def err_assoc_type_incomplete : Error<
+ "type %0 in generic association incomplete">;
+def err_assoc_type_nonobject : Error<
+ "type %0 in generic association not an object type">;
+def err_assoc_type_variably_modified : Error<
+ "type %0 in generic association is a variably modified type">;
+def err_assoc_compatible_types : Error<
+ "type %0 in generic association compatible with previously specified type %1">;
+def note_compat_assoc : Note<
+ "compatible type %0 specified here">;
+def err_generic_sel_no_match : Error<
+ "controlling expression type %0 not compatible with any generic association type">;
+def err_generic_sel_multi_match : Error<
+ "controlling expression type %0 compatible with %1 generic association types">;
// Blocks
diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td
index a25af44790..eaf4b85984 100644
--- a/include/clang/Basic/StmtNodes.td
+++ b/include/clang/Basic/StmtNodes.td
@@ -75,6 +75,7 @@ def DesignatedInitExpr : DStmt<Expr>;
def ImplicitValueInitExpr : DStmt<Expr>;
def ParenListExpr : DStmt<Expr>;
def VAArgExpr : DStmt<Expr>;
+def GenericSelectionExpr : DStmt<Expr>;
// GNU Extensions.
def AddrLabelExpr : DStmt<Expr>;
diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def
index d7d436c92c..e36803e959 100644
--- a/include/clang/Basic/TokenKinds.def
+++ b/include/clang/Basic/TokenKinds.def
@@ -238,6 +238,7 @@ KEYWORD(volatile , KEYALL)
KEYWORD(while , KEYALL)
KEYWORD(_Bool , KEYNOCXX)
KEYWORD(_Complex , KEYALL)
+KEYWORD(_Generic , KEYALL)
KEYWORD(_Imaginary , KEYALL)
KEYWORD(__func__ , KEYALL)
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index f10003fcd2..13972e6764 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1101,6 +1101,8 @@ private:
ExprResult ParseStringLiteralExpression();
+ ExprResult ParseGenericSelectionExpression();
+
//===--------------------------------------------------------------------===//
// C++ Expressions
ExprResult ParseCXXIdExpression(bool isAddressOfOperand = false);
diff --git a/include/clang/Sema/Ownership.h b/include/clang/Sema/Ownership.h
index 5f2f0eba71..cef93fe583 100644
--- a/include/clang/Sema/Ownership.h
+++ b/include/clang/Sema/Ownership.h
@@ -383,11 +383,18 @@ namespace clang {
template<typename T> T **takeAs() { return reinterpret_cast<T**>(take()); }
};
+ /// An opaque type for threading parsed type information through the
+ /// parser.
+ typedef OpaquePtr<QualType> ParsedType;
+ typedef UnionOpaquePtr<QualType> UnionParsedType;
+
/// A SmallVector of statements, with stack size 32 (as that is the only one
/// used.)
typedef ASTOwningVector<Stmt*, 32> StmtVector;
/// A SmallVector of expressions, with stack size 12 (the maximum used.)
typedef ASTOwningVector<Expr*, 12> ExprVector;
+ /// A SmallVector of types.
+ typedef ASTOwningVector<ParsedType, 12> TypeVector;
template <class T, unsigned N> inline
ASTMultiPtr<T> move_arg(ASTOwningVector<T, N> &vec) {
@@ -421,11 +428,6 @@ namespace clang {
static const bool value = true;
};
- /// An opaque type for threading parsed type information through the
- /// parser.
- typedef OpaquePtr<QualType> ParsedType;
- typedef UnionOpaquePtr<QualType> UnionParsedType;
-
typedef ActionResult<Expr*> ExprResult;
typedef ActionResult<Stmt*> StmtResult;
typedef ActionResult<ParsedType> TypeResult;
@@ -440,6 +442,7 @@ namespace clang {
typedef ASTMultiPtr<Expr*> MultiExprArg;
typedef ASTMultiPtr<Stmt*> MultiStmtArg;
+ typedef ASTMultiPtr<ParsedType> MultiTypeArg;
typedef ASTMultiPtr<TemplateParameterList*> MultiTemplateParamsArg;
inline ExprResult ExprError() { return ExprResult(true); }
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index f03bfe49b4..1879ed9129 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -2009,6 +2009,20 @@ public:
/// fragments (e.g. "foo" "bar" L"baz").
ExprResult ActOnStringLiteral(const Token *Toks, unsigned NumToks);
+ ExprResult ActOnGenericSelectionExpr(SourceLocation KeyLoc,
+ SourceLocation DefaultLoc,
+ SourceLocation RParenLoc,
+ Expr *ControllingExpr,
+ MultiTypeArg Types,
+ MultiExprArg Exprs);
+ ExprResult CreateGenericSelectionExpr(SourceLocation KeyLoc,
+ SourceLocation DefaultLoc,
+ SourceLocation RParenLoc,
+ Expr *ControllingExpr,
+ TypeSourceInfo **Types,
+ Expr **Exprs,
+ unsigned NumAssocs);
+
// Binary/Unary Operators. 'Tok' is the token for the operator.
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc,
Expr *InputArg);
diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h
index 35d6fe7f3b..e00fb3ae8b 100644
--- a/include/clang/Serialization/ASTBitCodes.h
+++ b/include/clang/Serialization/ASTBitCodes.h
@@ -878,6 +878,8 @@ namespace clang {
EXPR_BLOCK,
/// \brief A BlockDeclRef record.
EXPR_BLOCK_DECL_REF,
+ /// \brief A GenericSelectionExpr record.
+ EXPR_GENERIC_SELECTION,
// Objective-C