diff options
Diffstat (limited to 'include/clang')
-rw-r--r-- | include/clang/AST/Expr.h | 112 | ||||
-rw-r--r-- | include/clang/AST/RecursiveASTVisitor.h | 16 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticParseKinds.td | 7 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 15 | ||||
-rw-r--r-- | include/clang/Basic/StmtNodes.td | 1 | ||||
-rw-r--r-- | include/clang/Basic/TokenKinds.def | 1 | ||||
-rw-r--r-- | include/clang/Parse/Parser.h | 2 | ||||
-rw-r--r-- | include/clang/Sema/Ownership.h | 13 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 14 | ||||
-rw-r--r-- | include/clang/Serialization/ASTBitCodes.h | 2 |
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 |