Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11636,6 +11636,38 @@ "references to WebAssembly reference types are illegal">; def err_wasm_capture_reference : Error< "cannot capture WebAssembly reference">; +def err_wasm_table_pointer : Error< + "pointers to WebAssembly tables are illegal">; +def err_wasm_table_reference : Error< + "references to WebAssembly tables are illegal">; def err_wasm_addrof_reference : Error< "cannot take address of WebAssembly reference">; +def err_wasm_addrof_table : Error< + "cannot take address of WebAssembly table">; +def err_typecheck_wasm_table_must_have_zero_length : Error< + "only zero-length WebAssembly tables are currently supported">; +def err_wasm_table_in_function : Error< + "WebAssembly table cannot be declared within a function">; +def err_wasm_table_as_function_argument : Error< + "cannot use WebAssembly table as a function argument">; +def err_wasm_table_invalid_uett_operand : Error< + "invalid application of '%0' to WebAssembly table">; +def err_wasm_cast_table : Error< + "cannot cast WebAssembly table">; +def err_wasm_table_conditional_expression : Error< + "cannot use WebAssembly tables as the 2nd or 3rd operands of a conditional expression">; +def err_wasm_table_assignment : Error< + "cannot assign WebAssembly table to a variable">; +def err_wasm_table_return : Error< + "cannot return a WebAssembly table">; +def err_wasm_table_throw : Error< + "cannot throw a WebAssembly table">; +def err_wasm_table_catch : Error< + "cannot catch WebAssembly table">; +def err_wasm_table_exception_spec : Error< + "WebAssembly table not allowed in exception sepcification">; +def err_wasm_table_must_be_static : Error< + "WebAssembly table must be static">; +def err_wasm_multidimensional_ref_array : Error< + "multi-dimensional arrays of WebAssembly references are illegal">; } // end of sema component. Index: clang/lib/Sema/SemaCast.cpp =================================================================== --- clang/lib/Sema/SemaCast.cpp +++ clang/lib/Sema/SemaCast.cpp @@ -2895,6 +2895,14 @@ return; QualType SrcType = SrcExpr.get()->getType(); + if (SrcType->isPointerType() && + SrcType->getPointeeType()->isWebAssemblyReferenceType()) { + Self.Diag(OpRange.getBegin(), diag::err_wasm_cast_table) + << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); + return; + } + assert(!SrcType->isPlaceholderType()); checkAddressSpaceCast(SrcType, DestType); Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ clang/lib/Sema/SemaChecking.cpp @@ -11787,6 +11787,13 @@ } } + if (RetValExp) { + if (RetValExp->getType()->isPointerType() && + RetValExp->getType()->getPointeeType()->isWebAssemblyReferenceType()) { + Diag(ReturnLoc, diag::err_wasm_table_return); + } + } + // PPC MMA non-pointer types are not allowed as return type. Checking the type // here prevent the user from using a PPC MMA type as trailing return type. if (Context.getTargetInfo().getTriple().isPPC64()) @@ -15427,6 +15434,15 @@ RD, /*DeclIsField*/ false); } } + + if (!Param->isInvalidDecl() && Param->getOriginalType()->isArrayType() && + Param->getOriginalType() + ->getArrayElementTypeNoTypeQual() + ->isWebAssemblyReferenceType()) { + Param->setInvalidDecl(); + HasInvalidParm = true; + Diag(Param->getLocation(), diag::err_wasm_table_as_function_argument); + } } return HasInvalidParm; Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -7595,6 +7595,18 @@ } } + // WebAssembly tables are always in address space 1 (wasm_var). Don't apply + // address space if the table has local storage (semantic checks elsewhere + // will produce an error anyway). + if (const Type *ElTy = NewVD->getType()->getArrayElementTypeNoTypeQual()) { + if (ElTy && ElTy->isWebAssemblyReferenceType() && + !NewVD->hasLocalStorage()) { + QualType Type = Context.getAddrSpaceQualType( + NewVD->getType(), Context.getLangASForBuiltinAddressSpace(1)); + NewVD->setType(Type); + } + } + // Handle attributes prior to checking for duplicates in MergeVarDecl ProcessDeclAttributes(S, NewVD, D); @@ -8355,6 +8367,29 @@ } } + // WebAssembly tables must be static with a zero length and can't be + // declared within functions. + if (Context.getTargetInfo().getTriple().isWasm() && T->isArrayType() && + T->getArrayElementTypeNoTypeQual()->isWebAssemblyReferenceType()) { + if (getCurScope()->isFunctionScope()) { + Diag(NewVD->getLocation(), diag::err_wasm_table_in_function); + NewVD->setInvalidDecl(); + return; + } + if (NewVD->getStorageClass() != SC_Static) { + Diag(NewVD->getLocation(), diag::err_wasm_table_must_be_static); + NewVD->setInvalidDecl(); + return; + } + const auto *ATy = dyn_cast(T.getTypePtr()); + if (!ATy || ATy->getSize().getSExtValue() != 0) { + Diag(NewVD->getLocation(), + diag::err_typecheck_wasm_table_must_have_zero_length); + NewVD->setInvalidDecl(); + return; + } + } + bool isVM = T->isVariablyModifiedType(); if (isVM || NewVD->hasAttr() || NewVD->hasAttr()) @@ -10325,6 +10360,18 @@ } } } + // WebAssembly tables can't be used as function parameters. + if (Context.getTargetInfo().getTriple().isWasm()) { + while (PT->isPointerType()) { + PT = PT->getPointeeType(); + if (PT->isWebAssemblyReferenceType() || + PT->getBaseElementTypeUnsafe()->isWebAssemblyReferenceType()) { + Diag(Param->getTypeSpecStartLoc(), + diag::err_wasm_table_as_function_argument); + D.setInvalidType(); + } + } + } } // Here we have an function template explicit specialization at class scope. @@ -12522,6 +12569,16 @@ return; } + // WebAssembly tables can't be used to initialise a variable. + if (Init && !Init->getType().isNull() && Init->getType()->isArrayType() && + Init->getType() + ->getArrayElementTypeNoTypeQual() + ->isWebAssemblyReferenceType()) { + Diag(Init->getExprLoc(), diag::err_wasm_table_assignment); + VDecl->setInvalidDecl(); + return; + } + // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. if (VDecl->getType()->isUndeducedType()) { // Attempt typo correction early so that the type of the init expression can Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -16396,6 +16396,11 @@ Invalid = true; } + if (!Invalid && BaseType->isWebAssemblyReferenceType()) { + Diag(Loc, diag::err_wasm_table_catch); + Invalid = true; + } + if (!Invalid && !ExDeclType->isDependentType() && RequireNonAbstractType(Loc, ExDeclType, diag::err_abstract_type_in_decl, Index: clang/lib/Sema/SemaExceptionSpec.cpp =================================================================== --- clang/lib/Sema/SemaExceptionSpec.cpp +++ clang/lib/Sema/SemaExceptionSpec.cpp @@ -118,6 +118,7 @@ /// \param[in,out] T The exception type. This will be decayed to a pointer type /// when the input is an array or a function type. bool Sema::CheckSpecifiedExceptionType(QualType &T, SourceRange Range) { + // C++11 [except.spec]p2: // A type cv T, "array of T", or "function returning T" denoted // in an exception-specification is adjusted to type T, "pointer to T", or @@ -179,6 +180,12 @@ return true; } + // WebAssembly tables can't be used in exception specifications. + if (PointeeT->isWebAssemblyReferenceType()) { + Diag(Range.getBegin(), diag::err_wasm_table_exception_spec); + return true; + } + return false; } Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -4282,6 +4282,17 @@ E->getSourceRange(), ExprKind)) return false; + // WebAssembly tables are always illegal operands to unary expressions and + // type traits. + if (Context.getTargetInfo().getTriple().isWasm()) { + const Type *ElTy = E->getType()->getArrayElementTypeNoTypeQual(); + if (ElTy && ElTy->isWebAssemblyReferenceType()) { + Diag(E->getExprLoc(), diag::err_wasm_table_invalid_uett_operand) + << getTraitSpelling(ExprKind); + return true; + } + } + // 'alignof' applied to an expression only requires the base element type of // the expression to be complete. 'sizeof' requires the expression's type to // be complete (and will attempt to complete it if it's an array of unknown @@ -4397,6 +4408,17 @@ return true; } + // WebAssembly tables are always illegal operands to unary expressions and + // type traits. + if (Context.getTargetInfo().getTriple().isWasm()) { + const Type *ElTy = ExprType->getBaseElementTypeUnsafe(); + if (ElTy != ExprType.getTypePtr() && ElTy->isWebAssemblyReferenceType()) { + Diag(OpLoc, diag::err_wasm_table_invalid_uett_operand) + << getTraitSpelling(ExprKind); + return true; + } + } + if (CheckObjCTraitOperandConstraints(*this, ExprType, OpLoc, ExprRange, ExprKind)) return true; @@ -5807,6 +5829,7 @@ if (!ResultType.hasQualifiers()) VK = VK_PRValue; } else if (!ResultType->isDependentType() && + !ResultType->isWebAssemblyReferenceType() && RequireCompleteSizedType( LLoc, ResultType, diag::err_subscript_incomplete_or_sizeless_type, BaseExpr)) @@ -7083,6 +7106,21 @@ TheCall->setType(FuncT->getCallResultType(Context)); TheCall->setValueKind(Expr::getValueKindForType(FuncT->getReturnType())); + // WebAssembly tables can't be used as arguments. + if (Context.getTargetInfo().getTriple().isWasm()) { + for (const Expr *Arg : Args) { + if (Arg) { + if (const Type *ElTy = + Arg->getType()->getArrayElementTypeNoTypeQual()) { + if (ElTy && ElTy->isWebAssemblyReferenceType()) { + return ExprError(Diag(Arg->getExprLoc(), + diag::err_wasm_table_as_function_argument)); + } + } + } + } + } + if (Proto) { if (ConvertArgumentsForCall(TheCall, Fn, FDecl, Proto, Args, RParenLoc, IsExecConfig)) @@ -8633,6 +8671,14 @@ QualType LHSTy = LHS.get()->getType(); QualType RHSTy = RHS.get()->getType(); + if ((LHSTy->isPointerType() && + LHSTy->getPointeeType()->isWebAssemblyReferenceType()) || + (RHSTy->isPointerType() && + RHSTy->getPointeeType()->isWebAssemblyReferenceType())) { + Diag(QuestionLoc, diag::err_wasm_table_conditional_expression) + << LHS.get()->getSourceRange() << RHS.get()->getSourceRange(); + return QualType(); + } // Diagnose attempts to convert between __ibm128, __float128 and long double // where such conversions currently can't be handled. @@ -12336,6 +12382,12 @@ (RHSType->isArithmeticType() || RHSType->isEnumeralType())) return checkArithmeticOrEnumeralCompare(*this, LHS, RHS, Loc, Opc); + if ((LHSType->isPointerType() && + LHSType->getPointeeType()->isWebAssemblyReferenceType()) || + (RHSType->isPointerType() && + RHSType->getPointeeType()->isWebAssemblyReferenceType())) + return InvalidOperands(Loc, LHS, RHS); + const Expr::NullPointerConstantKind LHSNullKind = LHS.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull); const Expr::NullPointerConstantKind RHSNullKind = @@ -13230,6 +13282,16 @@ if (EnumConstantInBoolContext) Diag(Loc, diag::warn_enum_constant_in_bool_context); + // WebAssembly tables can't be used with logical operators. + QualType LHSTy = LHS.get()->getType(); + QualType RHSTy = RHS.get()->getType(); + if ((LHSTy->isArrayType() && + LHSTy->getArrayElementTypeNoTypeQual()->isWebAssemblyReferenceType()) || + (RHSTy->isArrayType() && + RHSTy->getArrayElementTypeNoTypeQual()->isWebAssemblyReferenceType())) { + return InvalidOperands(Loc, LHS, RHS); + } + // Diagnose cases where the user write a logical and/or but probably meant a // bitwise one. We do this when the LHS is a non-bool integer and the RHS // is a constant. @@ -13770,6 +13832,13 @@ return QualType(); } + // WebAssembly tables can't be used on RHS of an assignment expression. + if (RHSType->isArrayType() && + RHSType->getArrayElementTypeNoTypeQual()->isWebAssemblyReferenceType()) { + Diag(Loc, diag::err_wasm_table_assignment); + return QualType(); + } + AssignConvertType ConvTy; if (CompoundType.isNull()) { Expr *RHSCheck = RHS.get(); @@ -14378,11 +14447,20 @@ if (op->getType()->isObjCObjectType()) return Context.getObjCObjectPointerType(op->getType()); - if (Context.getTargetInfo().getTriple().isWasm() && - op->getType()->isWebAssemblyReferenceType()) { - Diag(OpLoc, diag::err_wasm_addrof_reference) - << OrigOp.get()->getSourceRange(); - return QualType(); + // Cannot take the address of WebAssembly references or tables. + if (Context.getTargetInfo().getTriple().isWasm()) { + QualType OpTy = op->getType(); + if (OpTy->isWebAssemblyReferenceType()) { + Diag(OpLoc, diag::err_wasm_addrof_reference) + << OrigOp.get()->getSourceRange(); + return QualType(); + } + if (OpTy->isArrayType() && + OpTy->getArrayElementTypeNoTypeQual()->isWebAssemblyReferenceType()) { + Diag(OpLoc, diag::err_wasm_addrof_table) + << OrigOp.get()->getSourceRange(); + return QualType(); + } } CheckAddressOfPackedMember(op); @@ -15528,6 +15606,13 @@ resultType = Context.FloatTy; } + // WebAsembly tables can't be used in unary expressions. + if (resultType->isPointerType() && + resultType->getPointeeType()->isWebAssemblyReferenceType()) { + return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr) + << resultType << Input.get()->getSourceRange()); + } + if (resultType->isDependentType()) break; if (resultType->isScalarType() && !isScopedEnumerationType(resultType)) { Index: clang/lib/Sema/SemaExprCXX.cpp =================================================================== --- clang/lib/Sema/SemaExprCXX.cpp +++ clang/lib/Sema/SemaExprCXX.cpp @@ -989,6 +989,13 @@ return true; } + // Cannot throw WebAssembly tables (throwing WebAssembly references is + // caught earlier in this function). + if (Ty->isWebAssemblyReferenceType()) { + Diag(ThrowLoc, diag::err_wasm_table_throw) << E->getSourceRange(); + return true; + } + // If the exception has class type, we need additional handling. CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); if (!RD) Index: clang/lib/Sema/SemaStmt.cpp =================================================================== --- clang/lib/Sema/SemaStmt.cpp +++ clang/lib/Sema/SemaStmt.cpp @@ -3971,6 +3971,16 @@ } else // If we don't have a function/method context, bail. return StmtError(); + if (RetValExp) { + if (RetValExp->getType()->isArrayType() && + RetValExp->getType() + ->getArrayElementTypeNoTypeQual() + ->isWebAssemblyReferenceType()) { + Diag(ReturnLoc, diag::err_wasm_table_return); + return StmtError(); + } + } + // C++1z: discarded return statements are not considered when deducing a // return type. if (ExprEvalContexts.back().isDiscardedStatementContext() && Index: clang/lib/Sema/SemaType.cpp =================================================================== --- clang/lib/Sema/SemaType.cpp +++ clang/lib/Sema/SemaType.cpp @@ -2147,11 +2147,16 @@ if (getLangOpts().OpenCL) T = deduceOpenCLPointeeAddrSpace(*this, T); - // In WebAssembly, pointers to reference types are illegal. + // In WebAssembly, pointers to reference types and pointers to tables are + // illegal. if (getASTContext().getTargetInfo().getTriple().isWasm()) { if (T->isWebAssemblyReferenceType()) { Diag(Loc, diag::err_wasm_reference_pointer); return QualType(); + } else if (T->isArrayType() && T->getArrayElementTypeNoTypeQual() + ->isWebAssemblyReferenceType()) { + Diag(Loc, diag::err_wasm_table_pointer); + return QualType(); } } @@ -2230,11 +2235,15 @@ if (getLangOpts().OpenCL) T = deduceOpenCLPointeeAddrSpace(*this, T); - // In WebAssembly, references to reference types are illegal. + // In WebAssembly, references to reference types and tables are illegal. if (getASTContext().getTargetInfo().getTriple().isWasm()) { if (T->isWebAssemblyReferenceType()) { Diag(Loc, diag::err_wasm_reference_reference); return QualType(); + } else if (T->isArrayType() && T->getArrayElementTypeNoTypeQual() + ->isWebAssemblyReferenceType()) { + Diag(Loc, diag::err_wasm_table_reference); + return QualType(); } } @@ -2424,12 +2433,22 @@ } else { // C99 6.7.5.2p1: If the element type is an incomplete or function type, // reject it (e.g. void ary[7], struct foo ary[7], void ary[7]()) - if (RequireCompleteSizedType(Loc, T, + if (!T->isWebAssemblyReferenceType() && + RequireCompleteSizedType(Loc, T, diag::err_array_incomplete_or_sizeless_type)) return QualType(); } - if (T->isSizelessType()) { + // Multi-dimensional arrays of WebAssembly references are not allowed. + if (Context.getTargetInfo().getTriple().isWasm() && T->isArrayType()) { + const Type *BaseTy = T->getBaseElementTypeUnsafe(); + if (BaseTy->isWebAssemblyReferenceType()) { + Diag(Loc, diag::err_wasm_multidimensional_ref_array); + return QualType(); + } + } + + if (T->isSizelessType() && !T->isWebAssemblyReferenceType()) { Diag(Loc, diag::err_array_incomplete_or_sizeless_type) << 1 << T; return QualType(); } @@ -2909,6 +2928,10 @@ Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 0 << FixItHint::CreateInsertion(Loc, "*"); Invalid = true; + } else if (ParamType->isPointerType() && + ParamType->getPointeeType()->isWebAssemblyReferenceType()) { + Diag(Loc, diag::err_wasm_table_as_function_argument); + Invalid = true; } // C++2a [dcl.fct]p4: Index: clang/test/CodeGen/WebAssembly/table.c =================================================================== --- /dev/null +++ clang/test/CodeGen/WebAssembly/table.c @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -triple wasm32 -target-feature +reference-types -o - -emit-llvm %s | FileCheck %s +// REQUIRES: webassembly-registered-target + +// CHECK: @table = internal addrspace(1) global [0 x ptr addrspace(10)] zeroinitializer, align 1 +static __externref_t table[0]; + +void use() { + // Ensure the table isn't discarded as unused. + table[0]; +} Index: clang/test/Sema/wasm-refs-and-tables.c =================================================================== --- clang/test/Sema/wasm-refs-and-tables.c +++ clang/test/Sema/wasm-refs-and-tables.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -triple wasm32 -target-feature +reference-types %s +// RUN: %clang_cc1 -fsyntax-only -verify -triple wasm32 -Wno-unused-value -target-feature +reference-types %s // Note: As WebAssembly references are sizeless types, we don't exhaustively // test for cases covered by sizeless-1.c and similar tests. @@ -11,39 +11,45 @@ __externref_t *t1; // expected-error {{pointers to WebAssembly reference types are illegal}} __externref_t **t2; // expected-error {{pointers to WebAssembly reference types are illegal}} __externref_t ******t3; // expected-error {{pointers to WebAssembly reference types are illegal}} -static __externref_t t4[3]; // expected-error {{array has sizeless element type '__externref_t'}} -static __externref_t t5[]; // expected-error {{array has sizeless element type '__externref_t'}} -static __externref_t t6[] = {0}; // expected-error {{array has sizeless element type '__externref_t'}} -__externref_t t7[0]; // expected-error {{array has sizeless element type '__externref_t'}} -static __externref_t t8[0][0]; // expected-error {{array has sizeless element type '__externref_t'}} +static __externref_t t4[3]; // expected-error {{only zero-length WebAssembly tables are currently supported}} +static __externref_t t5[]; // expected-error {{only zero-length WebAssembly tables are currently supported}} +static __externref_t t6[] = {0}; // expected-error {{only zero-length WebAssembly tables are currently supported}} +__externref_t t7[0]; // expected-error {{WebAssembly table must be static}} +static __externref_t t8[0][0]; // expected-error {{multi-dimensional arrays of WebAssembly references are illegal}} +static __externref_t (*t9)[0]; // expected-error {{pointers to WebAssembly tables are illegal}} -static __externref_t table[0]; // expected-error {{array has sizeless element type '__externref_t'}} +static __externref_t table[0]; +static __externref_t other_table[0] = {}; struct s { __externref_t f1; // expected-error {{field has sizeless type '__externref_t'}} - __externref_t f2[0]; // expected-error {{array has sizeless element type '__externref_t'}} - __externref_t f3[]; // expected-error {{array has sizeless element type '__externref_t'}} - __externref_t f4[0][0]; // expected-error {{array has sizeless element type '__externref_t'}} + __externref_t f2[0]; // expected-error {{field has sizeless type '__externref_t'}} + __externref_t f3[]; // expected-error {{field has sizeless type '__externref_t'}} + __externref_t f4[0][0]; // expected-error {{multi-dimensional arrays of WebAssembly references are illegal}} __externref_t *f5; // expected-error {{pointers to WebAssembly reference types are illegal}} __externref_t ****f6; // expected-error {{pointers to WebAssembly reference types are illegal}} + __externref_t (*f7)[0]; // expected-error {{pointers to WebAssembly tables are illegal}} }; union u { __externref_t f1; // expected-error {{field has sizeless type '__externref_t'}} - __externref_t f2[0]; // expected-error {{array has sizeless element type '__externref_t'}} - __externref_t f3[]; // expected-error {{array has sizeless element type '__externref_t'}} - __externref_t f4[0][0]; // expected-error {{array has sizeless element type '__externref_t'}} + __externref_t f2[0]; // expected-error {{field has sizeless type '__externref_t'}} + __externref_t f3[]; // expected-error {{field has sizeless type '__externref_t'}} + __externref_t f4[0][0]; // expected-error {{multi-dimensional arrays of WebAssembly references are illegal}} __externref_t *f5; // expected-error {{pointers to WebAssembly reference types are illegal}} __externref_t ****f6; // expected-error {{pointers to WebAssembly reference types are illegal}} + __externref_t (*f7)[0]; // expected-error {{pointers to WebAssembly tables are illegal}} }; -void illegal_argument_1(__externref_t table[]); // expected-error {{array has sizeless element type '__externref_t'}} -void illegal_argument_2(__externref_t table[0][0]); // expected-error {{array has sizeless element type '__externref_t'}} +void illegal_argument_1(__externref_t table[]); // expected-error {{cannot use WebAssembly table as a function argument}} +void illegal_argument_2(__externref_t table[0][0]); // expected-error {{multi-dimensional arrays of WebAssembly references are illegal}} void illegal_argument_3(__externref_t *table); // expected-error {{pointers to WebAssembly reference types are illegal}} void illegal_argument_4(__externref_t ***table); // expected-error {{pointers to WebAssembly reference types are illegal}} +void illegal_argument_5(__externref_t (*table)[0]); // expected-error {{pointers to WebAssembly tables are illegal}} __externref_t *illegal_return_1(); // expected-error {{pointers to WebAssembly reference types are illegal}} __externref_t ***illegal_return_2(); // expected-error {{pointers to WebAssembly reference types are illegal}} +__externref_t (*illegal_return_3())[0]; // expected-error {{pointers to WebAssembly tables are illegal}} void varargs(int, ...); @@ -54,18 +60,45 @@ (__externref_t ****)(&foo); // expected-error {{pointers to WebAssembly reference types are illegal}} sizeof(ref); // expected-error {{invalid application of 'sizeof' to sizeless type '__externref_t'}} sizeof(__externref_t); // expected-error {{invalid application of 'sizeof' to sizeless type '__externref_t'}} - sizeof(__externref_t[0]); // expected-error {{array has sizeless element type '__externref_t'}} - sizeof(__externref_t[0][0]); // expected-error {{array has sizeless element type '__externref_t'}} + sizeof(__externref_t[0]); // expected-error {{invalid application of 'sizeof' to WebAssembly table}} + sizeof(table); // expected-error {{invalid application of 'sizeof' to WebAssembly table}} + sizeof(__externref_t[0][0]); // expected-error {{multi-dimensional arrays of WebAssembly references are illegal}} sizeof(__externref_t *); // expected-error {{pointers to WebAssembly reference types are illegal}} sizeof(__externref_t ***); // expected-error {{pointers to WebAssembly reference types are illegal}}; // expected-warning@+1 {{'_Alignof' applied to an expression is a GNU extension}} _Alignof(ref); // expected-error {{invalid application of 'alignof' to sizeless type '__externref_t'}} _Alignof(__externref_t); // expected-error {{invalid application of 'alignof' to sizeless type '__externref_t'}} - _Alignof(__externref_t[]); // expected-error {{array has sizeless element type '__externref_t'}} - _Alignof(__externref_t[0][0]); // expected-error {{array has sizeless element type '__externref_t'}} + _Alignof(__externref_t[]); // expected-error {{invalid application of 'alignof' to sizeless type '__externref_t'}} + _Alignof(__externref_t[0]); // expected-error {{invalid application of 'alignof' to sizeless type '__externref_t'}} + _Alignof(table); // expected-warning {{'_Alignof' applied to an expression is a GNU extension}} expected-error {{invalid application of 'alignof' to WebAssembly table}} + _Alignof(__externref_t[0][0]); // expected-error {{multi-dimensional arrays of WebAssembly references are illegal}} _Alignof(__externref_t *); // expected-error {{pointers to WebAssembly reference types are illegal}} _Alignof(__externref_t ***); // expected-error {{pointers to WebAssembly reference types are illegal}}; varargs(1, ref); // expected-error {{cannot pass expression of type '__externref_t' to variadic function}} + __externref_t lt1[0]; // expected-error {{WebAssembly table cannot be declared within a function}} + static __externref_t lt2[0]; // expected-error {{WebAssembly table cannot be declared within a function}} + static __externref_t lt3[0][0]; // expected-error {{multi-dimensional arrays of WebAssembly references are illegal}} + static __externref_t(*lt4)[0]; // expected-error {{pointers to WebAssembly tables are illegal}} + illegal_argument_1(table); // expected-error {{cannot use WebAssembly table as a function argument}} + varargs(1, table); // expected-error {{cannot use WebAssembly table as a function argument}} + table == 1; // expected-error {{invalid operands to binary expression ('__attribute__((address_space(1))) __externref_t[0]' and 'int')}} + 1 >= table; // expected-error {{invalid operands to binary expression ('int' and '__attribute__((address_space(1))) __externref_t[0]')}} + !table; // expected-error {{invalid argument type '__attribute__((address_space(1))) __externref_t *' to unary expression}} + 1 && table; // expected-error {{invalid operands to binary expression ('int' and '__attribute__((address_space(1))) __externref_t[0]')}} + table || 1; // expected-error {{invalid operands to binary expression ('__attribute__((address_space(1))) __externref_t[0]' and 'int')}} + 1 ? table : table; // expected-error {{cannot use WebAssembly tables as the 2nd or 3rd operands of a conditional expression}} + (void *)table; // expected-error {{cannot cast WebAssembly table}} + void *u; + u = table; // expected-error {{cannot assign WebAssembly table to a variable}} + void *v = table; // expected-error {{cannot assign WebAssembly table to a variable}} + &table; // expected-error {{cannot take address of WebAssembly table}} + + table[0]; + table[0] = ref; return ref; } + +void *ret_void_ptr() { + return table; // expected-error {{cannot return a WebAssembly table}} +} Index: clang/test/SemaCXX/wasm-refs-and-tables.cpp =================================================================== --- clang/test/SemaCXX/wasm-refs-and-tables.cpp +++ clang/test/SemaCXX/wasm-refs-and-tables.cpp @@ -7,40 +7,40 @@ __externref_t &ref_ref1 = ref; // expected-error {{references to WebAssembly reference types are illegal}} __externref_t &ref_ref2(ref); // expected-error {{references to WebAssembly reference types are illegal}} -static __externref_t table[0]; // expected-error {{array has sizeless element type '__externref_t'}} -static __externref_t (&ref_to_table1)[0] = table; // expected-error {{array has sizeless element type '__externref_t'}} -static __externref_t (&ref_to_table2)[0](table); // expected-error {{array has sizeless element type '__externref_t'}} +static __externref_t table[0]; // expected-note 2 {{'table' declared here}} +static __externref_t (&ref_to_table1)[0] = table; // expected-error {{references to WebAssembly tables are illegal}} +static __externref_t (&ref_to_table2)[0](table); // expected-error {{references to WebAssembly tables are illegal}} void illegal_argument_1(__externref_t &r); // expected-error {{references to WebAssembly reference types are illegal}} -void illegal_argument_2(__externref_t (&t)[0]); // expected-error {{array has sizeless element type '__externref_t'}} +void illegal_argument_2(__externref_t (&t)[0]); // expected-error {{references to WebAssembly tables are illegal}} __externref_t &illegal_return_1(); // expected-error {{references to WebAssembly reference types are illegal}} -__externref_t (&illegal_return_2())[0]; // expected-error {{array has sizeless element type '__externref_t'}} +__externref_t (&illegal_return_2())[0]; // expected-error {{references to WebAssembly tables are illegal}} void illegal_throw1() throw(__externref_t); // expected-error {{sizeless type '__externref_t' is not allowed in exception specification}} void illegal_throw2() throw(__externref_t *); // expected-error {{pointers to WebAssembly reference types are illegal}} void illegal_throw3() throw(__externref_t &); // expected-error {{references to WebAssembly reference types are illegal}} -void illegal_throw4() throw(__externref_t[0]); // expected-error {{array has sizeless element type '__externref_t'}} +void illegal_throw4() throw(__externref_t[0]); // expected-error {{WebAssembly table not allowed in exception sepcification}} class RefClass { __externref_t f1; // expected-error {{field has sizeless type '__externref_t'}} - __externref_t f2[0]; // expected-error {{array has sizeless element type '__externref_t'}} - __externref_t f3[]; // expected-error {{array has sizeless element type '__externref_t'}} - __externref_t f4[0][0]; // expected-error {{array has sizeless element type '__externref_t'}} + __externref_t f2[0]; // expected-error {{field has sizeless type '__externref_t'}} + __externref_t f3[]; // expected-error {{field has sizeless type '__externref_t'}} + __externref_t f4[0][0]; // expected-error {{multi-dimensional arrays of WebAssembly references are illegal}} __externref_t *f5; // expected-error {{pointers to WebAssembly reference types are illegal}} __externref_t ****f6; // expected-error {{pointers to WebAssembly reference types are illegal}} - __externref_t (*f7)[0]; // expected-error {{array has sizeless element type '__externref_t'}} + __externref_t (*f7)[0]; // expected-error {{pointers to WebAssembly tables are illegal}} }; struct AStruct {}; template struct TemplatedStruct { - T f; // expected-error {{field has sizeless type '__externref_t'}} - void foo(T); - T bar(void); - T arr[0]; // expected-error {{array has sizeless element type '__externref_t'}} - T *ptr; // expected-error {{pointers to WebAssembly reference types are illegal}} + T f; // expected-error 2 {{field has sizeless type '__externref_t'}} + void foo(T); // expected-error {{cannot use WebAssembly table as a function argument}} + T bar(void); // expected-error {{function cannot return array type '__externref_t[0]'}} + T arr[0]; // expected-error {{field has sizeless type '__externref_t'}} expected-error {{multi-dimensional arrays of WebAssembly references are illegal}} + T *ptr; // expected-error {{pointers to WebAssembly reference types are illegal}} expected-error {{pointers to WebAssembly tables are illegal}} }; void func() { @@ -50,38 +50,51 @@ static_cast(ref); // expected-error {{static_cast from '__externref_t' to 'int' is not allowed}} __externref_t(10); // expected-error {{functional-style cast from 'int' to '__externref_t' is not allowed}} int i(ref); // expected-error {{cannot initialize a variable of type 'int' with an lvalue of type '__externref_t'}} - const_cast<__externref_t[0]>(table); // expected-error {{array has sizeless element type '__externref_t'}} + int j(table); // expected-error {{cannot initialize a variable of type 'int' with an lvalue of type '__attribute__((address_space(1))) __externref_t[0]'}} + const_cast<__externref_t[0]>(table); // expected-error {{const_cast to '__externref_t[0]', which is not a reference, pointer-to-object, or pointer-to-data-member}} const_cast<__externref_t *>(table); // expected-error {{pointers to WebAssembly reference types are illegal}} reinterpret_cast<__externref_t>(foo); // expected-error {{reinterpret_cast from 'int' to '__externref_t' is not allowed}} reinterpret_cast(ref); // expected-error {{reinterpret_cast from '__externref_t' to 'int' is not allowed}} + reinterpret_cast(table); // expected-error {{reinterpret_cast from '__attribute__((address_space(1))) __externref_t *' to 'int *' is not allowed}} int iarr[0]; - reinterpret_cast<__externref_t[0]>(iarr); // expected-error {{array has sizeless element type '__externref_t'}} + reinterpret_cast<__externref_t[0]>(iarr); // expected-error {{reinterpret_cast from 'int *' to '__externref_t[0]' is not allowed}} reinterpret_cast<__externref_t *>(iarr); // expected-error {{pointers to WebAssembly reference types are illegal}} dynamic_cast<__externref_t>(foo); // expected-error {{invalid target type '__externref_t' for dynamic_cast; target type must be a reference or pointer type to a defined class}} dynamic_cast<__externref_t *>(&foo); // expected-error {{pointers to WebAssembly reference types are illegal}} + dynamic_cast(table); // expected-error {{'__externref_t' is not a class type}} + + for (auto x : table) { // expected-error {{cannot assign WebAssembly table to a variable}} + } TemplatedStruct<__externref_t> ts1; // expected-note {{in instantiation}} TemplatedStruct<__externref_t *> ts2; // expected-error {{pointers to WebAssembly reference types are illegal}} TemplatedStruct<__externref_t &> ts3; // expected-error {{references to WebAssembly reference types are illegal}} - TemplatedStruct<__externref_t[0]> ts4; // expected-error {{array has sizeless element type '__externref_t'}} + TemplatedStruct<__externref_t[0]> ts4; // expected-note {{in instantiation}} + auto auto_table = table; // expected-error {{cannot assign WebAssembly table to a variable}} auto auto_ref = ref; auto fn1 = [](__externref_t x) { return x; }; auto fn2 = [](__externref_t *x) { return x; }; // expected-error {{pointers to WebAssembly reference types are illegal}} auto fn3 = [](__externref_t &x) { return x; }; // expected-error {{references to WebAssembly reference types are illegal}} - auto fn4 = [](__externref_t x[0]) { return x; }; // expected-error {{array has sizeless element type '__externref_t'}} - auto fn5 = [&auto_ref](void) { return true; }; // expected-error {{cannot capture WebAssembly reference}} - auto fn6 = [auto_ref](void) { return true; }; // expected-error {{cannot capture WebAssembly reference}} - auto fn7 = [&](void) { auto_ref; return true; }; // expected-error {{cannot capture WebAssembly reference}} - auto fn8 = [=](void) { auto_ref; return true; }; // expected-error {{cannot capture WebAssembly reference}} + auto fn4 = [](__externref_t x[0]) { return x; }; // expected-error {{cannot use WebAssembly table as a function argument}} + auto fn5 = [](void) { return table; }; // expected-error {{cannot return a WebAssembly table}} + auto fn6 = [&auto_ref](void) { return true; }; // expected-error {{cannot capture WebAssembly reference}} + auto fn7 = [auto_ref](void) { return true; }; // expected-error {{cannot capture WebAssembly reference}} + auto fn8 = [&](void) { auto_ref; return true; }; // expected-error {{cannot capture WebAssembly reference}} + auto fn9 = [=](void) { auto_ref; return true; }; // expected-error {{cannot capture WebAssembly reference}} + auto fn10 = [table](void) { return true; }; // expected-error {{'table' cannot be captured because it does not have automatic storage duration}} + auto fn11 = [&table](void) { return true; }; // expected-error {{'table' cannot be captured because it does not have automatic storage duration}} alignof(__externref_t); // expected-error {{invalid application of 'alignof' to sizeless type '__externref_t'}} alignof(ref); // expected-warning {{'alignof' applied to an expression is a GNU extension}} expected-error {{invalid application of 'alignof' to sizeless type '__externref_t'}} - alignof(__externref_t[0]); // expected-error {{array has sizeless element type '__externref_t'}} + alignof(__externref_t[0]); // expected-error {{invalid application of 'alignof' to sizeless type '__externref_t'}} + alignof(table); // expected-warning {{'alignof' applied to an expression is a GNU extension}} expected-error {{invalid application of 'alignof' to WebAssembly table}} throw ref; // expected-error {{cannot throw object of sizeless type '__externref_t'}} throw &ref; // expected-error {{cannot take address of WebAssembly reference}} + throw table; // expected-error {{cannot throw a WebAssembly table}} + throw &table; // expected-error {{cannot take address of WebAssembly table}} try { } catch (__externref_t) { // expected-error {{cannot catch sizeless type '__externref_t'}} @@ -93,11 +106,12 @@ } catch (__externref_t &) { // expected-error {{references to WebAssembly reference types are illegal}} } try { - } catch (__externref_t[0]) { // expected-error {{array has sizeless element type '__externref_t'}} + } catch (__externref_t[0]) { // expected-error {{cannot catch WebAssembly table}} } new __externref_t; // expected-error {{allocation of sizeless type '__externref_t'}} new __externref_t[0]; // expected-error {{allocation of sizeless type '__externref_t'}} delete ref; // expected-error {{cannot delete expression of type '__externref_t'}} + delete[] table; // expected-error {{annot delete expression of type '__attribute__((address_space(1))) __externref_t[0]'}} }