1*0fca6ea1SDimitry Andric //===------ SemaWasm.cpp ---- WebAssembly target-specific routines --------===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric //
9*0fca6ea1SDimitry Andric // This file implements semantic analysis functions specific to WebAssembly.
10*0fca6ea1SDimitry Andric //
11*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
12*0fca6ea1SDimitry Andric
13*0fca6ea1SDimitry Andric #include "clang/Sema/SemaWasm.h"
14*0fca6ea1SDimitry Andric #include "clang/AST/ASTContext.h"
15*0fca6ea1SDimitry Andric #include "clang/AST/Decl.h"
16*0fca6ea1SDimitry Andric #include "clang/AST/Type.h"
17*0fca6ea1SDimitry Andric #include "clang/Basic/AddressSpaces.h"
18*0fca6ea1SDimitry Andric #include "clang/Basic/DiagnosticSema.h"
19*0fca6ea1SDimitry Andric #include "clang/Basic/TargetBuiltins.h"
20*0fca6ea1SDimitry Andric #include "clang/Sema/Attr.h"
21*0fca6ea1SDimitry Andric #include "clang/Sema/Sema.h"
22*0fca6ea1SDimitry Andric
23*0fca6ea1SDimitry Andric namespace clang {
24*0fca6ea1SDimitry Andric
SemaWasm(Sema & S)25*0fca6ea1SDimitry Andric SemaWasm::SemaWasm(Sema &S) : SemaBase(S) {}
26*0fca6ea1SDimitry Andric
27*0fca6ea1SDimitry Andric /// Checks the argument at the given index is a WebAssembly table and if it
28*0fca6ea1SDimitry Andric /// is, sets ElTy to the element type.
CheckWasmBuiltinArgIsTable(Sema & S,CallExpr * E,unsigned ArgIndex,QualType & ElTy)29*0fca6ea1SDimitry Andric static bool CheckWasmBuiltinArgIsTable(Sema &S, CallExpr *E, unsigned ArgIndex,
30*0fca6ea1SDimitry Andric QualType &ElTy) {
31*0fca6ea1SDimitry Andric Expr *ArgExpr = E->getArg(ArgIndex);
32*0fca6ea1SDimitry Andric const auto *ATy = dyn_cast<ArrayType>(ArgExpr->getType());
33*0fca6ea1SDimitry Andric if (!ATy || !ATy->getElementType().isWebAssemblyReferenceType()) {
34*0fca6ea1SDimitry Andric return S.Diag(ArgExpr->getBeginLoc(),
35*0fca6ea1SDimitry Andric diag::err_wasm_builtin_arg_must_be_table_type)
36*0fca6ea1SDimitry Andric << ArgIndex + 1 << ArgExpr->getSourceRange();
37*0fca6ea1SDimitry Andric }
38*0fca6ea1SDimitry Andric ElTy = ATy->getElementType();
39*0fca6ea1SDimitry Andric return false;
40*0fca6ea1SDimitry Andric }
41*0fca6ea1SDimitry Andric
42*0fca6ea1SDimitry Andric /// Checks the argument at the given index is an integer.
CheckWasmBuiltinArgIsInteger(Sema & S,CallExpr * E,unsigned ArgIndex)43*0fca6ea1SDimitry Andric static bool CheckWasmBuiltinArgIsInteger(Sema &S, CallExpr *E,
44*0fca6ea1SDimitry Andric unsigned ArgIndex) {
45*0fca6ea1SDimitry Andric Expr *ArgExpr = E->getArg(ArgIndex);
46*0fca6ea1SDimitry Andric if (!ArgExpr->getType()->isIntegerType()) {
47*0fca6ea1SDimitry Andric return S.Diag(ArgExpr->getBeginLoc(),
48*0fca6ea1SDimitry Andric diag::err_wasm_builtin_arg_must_be_integer_type)
49*0fca6ea1SDimitry Andric << ArgIndex + 1 << ArgExpr->getSourceRange();
50*0fca6ea1SDimitry Andric }
51*0fca6ea1SDimitry Andric return false;
52*0fca6ea1SDimitry Andric }
53*0fca6ea1SDimitry Andric
BuiltinWasmRefNullExtern(CallExpr * TheCall)54*0fca6ea1SDimitry Andric bool SemaWasm::BuiltinWasmRefNullExtern(CallExpr *TheCall) {
55*0fca6ea1SDimitry Andric if (TheCall->getNumArgs() != 0)
56*0fca6ea1SDimitry Andric return true;
57*0fca6ea1SDimitry Andric
58*0fca6ea1SDimitry Andric TheCall->setType(getASTContext().getWebAssemblyExternrefType());
59*0fca6ea1SDimitry Andric
60*0fca6ea1SDimitry Andric return false;
61*0fca6ea1SDimitry Andric }
62*0fca6ea1SDimitry Andric
BuiltinWasmRefNullFunc(CallExpr * TheCall)63*0fca6ea1SDimitry Andric bool SemaWasm::BuiltinWasmRefNullFunc(CallExpr *TheCall) {
64*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext();
65*0fca6ea1SDimitry Andric if (TheCall->getNumArgs() != 0) {
66*0fca6ea1SDimitry Andric Diag(TheCall->getBeginLoc(), diag::err_typecheck_call_too_many_args)
67*0fca6ea1SDimitry Andric << 0 /*function call*/ << /*expected*/ 0 << TheCall->getNumArgs()
68*0fca6ea1SDimitry Andric << /*is non object*/ 0;
69*0fca6ea1SDimitry Andric return true;
70*0fca6ea1SDimitry Andric }
71*0fca6ea1SDimitry Andric
72*0fca6ea1SDimitry Andric // This custom type checking code ensures that the nodes are as expected
73*0fca6ea1SDimitry Andric // in order to later on generate the necessary builtin.
74*0fca6ea1SDimitry Andric QualType Pointee = Context.getFunctionType(Context.VoidTy, {}, {});
75*0fca6ea1SDimitry Andric QualType Type = Context.getPointerType(Pointee);
76*0fca6ea1SDimitry Andric Pointee = Context.getAddrSpaceQualType(Pointee, LangAS::wasm_funcref);
77*0fca6ea1SDimitry Andric Type = Context.getAttributedType(attr::WebAssemblyFuncref, Type,
78*0fca6ea1SDimitry Andric Context.getPointerType(Pointee));
79*0fca6ea1SDimitry Andric TheCall->setType(Type);
80*0fca6ea1SDimitry Andric
81*0fca6ea1SDimitry Andric return false;
82*0fca6ea1SDimitry Andric }
83*0fca6ea1SDimitry Andric
84*0fca6ea1SDimitry Andric /// Check that the first argument is a WebAssembly table, and the second
85*0fca6ea1SDimitry Andric /// is an index to use as index into the table.
BuiltinWasmTableGet(CallExpr * TheCall)86*0fca6ea1SDimitry Andric bool SemaWasm::BuiltinWasmTableGet(CallExpr *TheCall) {
87*0fca6ea1SDimitry Andric if (SemaRef.checkArgCount(TheCall, 2))
88*0fca6ea1SDimitry Andric return true;
89*0fca6ea1SDimitry Andric
90*0fca6ea1SDimitry Andric QualType ElTy;
91*0fca6ea1SDimitry Andric if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 0, ElTy))
92*0fca6ea1SDimitry Andric return true;
93*0fca6ea1SDimitry Andric
94*0fca6ea1SDimitry Andric if (CheckWasmBuiltinArgIsInteger(SemaRef, TheCall, 1))
95*0fca6ea1SDimitry Andric return true;
96*0fca6ea1SDimitry Andric
97*0fca6ea1SDimitry Andric // If all is well, we set the type of TheCall to be the type of the
98*0fca6ea1SDimitry Andric // element of the table.
99*0fca6ea1SDimitry Andric // i.e. a table.get on an externref table has type externref,
100*0fca6ea1SDimitry Andric // or whatever the type of the table element is.
101*0fca6ea1SDimitry Andric TheCall->setType(ElTy);
102*0fca6ea1SDimitry Andric
103*0fca6ea1SDimitry Andric return false;
104*0fca6ea1SDimitry Andric }
105*0fca6ea1SDimitry Andric
106*0fca6ea1SDimitry Andric /// Check that the first argumnet is a WebAssembly table, the second is
107*0fca6ea1SDimitry Andric /// an index to use as index into the table and the third is the reference
108*0fca6ea1SDimitry Andric /// type to set into the table.
BuiltinWasmTableSet(CallExpr * TheCall)109*0fca6ea1SDimitry Andric bool SemaWasm::BuiltinWasmTableSet(CallExpr *TheCall) {
110*0fca6ea1SDimitry Andric if (SemaRef.checkArgCount(TheCall, 3))
111*0fca6ea1SDimitry Andric return true;
112*0fca6ea1SDimitry Andric
113*0fca6ea1SDimitry Andric QualType ElTy;
114*0fca6ea1SDimitry Andric if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 0, ElTy))
115*0fca6ea1SDimitry Andric return true;
116*0fca6ea1SDimitry Andric
117*0fca6ea1SDimitry Andric if (CheckWasmBuiltinArgIsInteger(SemaRef, TheCall, 1))
118*0fca6ea1SDimitry Andric return true;
119*0fca6ea1SDimitry Andric
120*0fca6ea1SDimitry Andric if (!getASTContext().hasSameType(ElTy, TheCall->getArg(2)->getType()))
121*0fca6ea1SDimitry Andric return true;
122*0fca6ea1SDimitry Andric
123*0fca6ea1SDimitry Andric return false;
124*0fca6ea1SDimitry Andric }
125*0fca6ea1SDimitry Andric
126*0fca6ea1SDimitry Andric /// Check that the argument is a WebAssembly table.
BuiltinWasmTableSize(CallExpr * TheCall)127*0fca6ea1SDimitry Andric bool SemaWasm::BuiltinWasmTableSize(CallExpr *TheCall) {
128*0fca6ea1SDimitry Andric if (SemaRef.checkArgCount(TheCall, 1))
129*0fca6ea1SDimitry Andric return true;
130*0fca6ea1SDimitry Andric
131*0fca6ea1SDimitry Andric QualType ElTy;
132*0fca6ea1SDimitry Andric if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 0, ElTy))
133*0fca6ea1SDimitry Andric return true;
134*0fca6ea1SDimitry Andric
135*0fca6ea1SDimitry Andric return false;
136*0fca6ea1SDimitry Andric }
137*0fca6ea1SDimitry Andric
138*0fca6ea1SDimitry Andric /// Check that the first argument is a WebAssembly table, the second is the
139*0fca6ea1SDimitry Andric /// value to use for new elements (of a type matching the table type), the
140*0fca6ea1SDimitry Andric /// third value is an integer.
BuiltinWasmTableGrow(CallExpr * TheCall)141*0fca6ea1SDimitry Andric bool SemaWasm::BuiltinWasmTableGrow(CallExpr *TheCall) {
142*0fca6ea1SDimitry Andric if (SemaRef.checkArgCount(TheCall, 3))
143*0fca6ea1SDimitry Andric return true;
144*0fca6ea1SDimitry Andric
145*0fca6ea1SDimitry Andric QualType ElTy;
146*0fca6ea1SDimitry Andric if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 0, ElTy))
147*0fca6ea1SDimitry Andric return true;
148*0fca6ea1SDimitry Andric
149*0fca6ea1SDimitry Andric Expr *NewElemArg = TheCall->getArg(1);
150*0fca6ea1SDimitry Andric if (!getASTContext().hasSameType(ElTy, NewElemArg->getType())) {
151*0fca6ea1SDimitry Andric return Diag(NewElemArg->getBeginLoc(),
152*0fca6ea1SDimitry Andric diag::err_wasm_builtin_arg_must_match_table_element_type)
153*0fca6ea1SDimitry Andric << 2 << 1 << NewElemArg->getSourceRange();
154*0fca6ea1SDimitry Andric }
155*0fca6ea1SDimitry Andric
156*0fca6ea1SDimitry Andric if (CheckWasmBuiltinArgIsInteger(SemaRef, TheCall, 2))
157*0fca6ea1SDimitry Andric return true;
158*0fca6ea1SDimitry Andric
159*0fca6ea1SDimitry Andric return false;
160*0fca6ea1SDimitry Andric }
161*0fca6ea1SDimitry Andric
162*0fca6ea1SDimitry Andric /// Check that the first argument is a WebAssembly table, the second is an
163*0fca6ea1SDimitry Andric /// integer, the third is the value to use to fill the table (of a type
164*0fca6ea1SDimitry Andric /// matching the table type), and the fourth is an integer.
BuiltinWasmTableFill(CallExpr * TheCall)165*0fca6ea1SDimitry Andric bool SemaWasm::BuiltinWasmTableFill(CallExpr *TheCall) {
166*0fca6ea1SDimitry Andric if (SemaRef.checkArgCount(TheCall, 4))
167*0fca6ea1SDimitry Andric return true;
168*0fca6ea1SDimitry Andric
169*0fca6ea1SDimitry Andric QualType ElTy;
170*0fca6ea1SDimitry Andric if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 0, ElTy))
171*0fca6ea1SDimitry Andric return true;
172*0fca6ea1SDimitry Andric
173*0fca6ea1SDimitry Andric if (CheckWasmBuiltinArgIsInteger(SemaRef, TheCall, 1))
174*0fca6ea1SDimitry Andric return true;
175*0fca6ea1SDimitry Andric
176*0fca6ea1SDimitry Andric Expr *NewElemArg = TheCall->getArg(2);
177*0fca6ea1SDimitry Andric if (!getASTContext().hasSameType(ElTy, NewElemArg->getType())) {
178*0fca6ea1SDimitry Andric return Diag(NewElemArg->getBeginLoc(),
179*0fca6ea1SDimitry Andric diag::err_wasm_builtin_arg_must_match_table_element_type)
180*0fca6ea1SDimitry Andric << 3 << 1 << NewElemArg->getSourceRange();
181*0fca6ea1SDimitry Andric }
182*0fca6ea1SDimitry Andric
183*0fca6ea1SDimitry Andric if (CheckWasmBuiltinArgIsInteger(SemaRef, TheCall, 3))
184*0fca6ea1SDimitry Andric return true;
185*0fca6ea1SDimitry Andric
186*0fca6ea1SDimitry Andric return false;
187*0fca6ea1SDimitry Andric }
188*0fca6ea1SDimitry Andric
189*0fca6ea1SDimitry Andric /// Check that the first argument is a WebAssembly table, the second is also a
190*0fca6ea1SDimitry Andric /// WebAssembly table (of the same element type), and the third to fifth
191*0fca6ea1SDimitry Andric /// arguments are integers.
BuiltinWasmTableCopy(CallExpr * TheCall)192*0fca6ea1SDimitry Andric bool SemaWasm::BuiltinWasmTableCopy(CallExpr *TheCall) {
193*0fca6ea1SDimitry Andric if (SemaRef.checkArgCount(TheCall, 5))
194*0fca6ea1SDimitry Andric return true;
195*0fca6ea1SDimitry Andric
196*0fca6ea1SDimitry Andric QualType XElTy;
197*0fca6ea1SDimitry Andric if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 0, XElTy))
198*0fca6ea1SDimitry Andric return true;
199*0fca6ea1SDimitry Andric
200*0fca6ea1SDimitry Andric QualType YElTy;
201*0fca6ea1SDimitry Andric if (CheckWasmBuiltinArgIsTable(SemaRef, TheCall, 1, YElTy))
202*0fca6ea1SDimitry Andric return true;
203*0fca6ea1SDimitry Andric
204*0fca6ea1SDimitry Andric Expr *TableYArg = TheCall->getArg(1);
205*0fca6ea1SDimitry Andric if (!getASTContext().hasSameType(XElTy, YElTy)) {
206*0fca6ea1SDimitry Andric return Diag(TableYArg->getBeginLoc(),
207*0fca6ea1SDimitry Andric diag::err_wasm_builtin_arg_must_match_table_element_type)
208*0fca6ea1SDimitry Andric << 2 << 1 << TableYArg->getSourceRange();
209*0fca6ea1SDimitry Andric }
210*0fca6ea1SDimitry Andric
211*0fca6ea1SDimitry Andric for (int I = 2; I <= 4; I++) {
212*0fca6ea1SDimitry Andric if (CheckWasmBuiltinArgIsInteger(SemaRef, TheCall, I))
213*0fca6ea1SDimitry Andric return true;
214*0fca6ea1SDimitry Andric }
215*0fca6ea1SDimitry Andric
216*0fca6ea1SDimitry Andric return false;
217*0fca6ea1SDimitry Andric }
218*0fca6ea1SDimitry Andric
CheckWebAssemblyBuiltinFunctionCall(const TargetInfo & TI,unsigned BuiltinID,CallExpr * TheCall)219*0fca6ea1SDimitry Andric bool SemaWasm::CheckWebAssemblyBuiltinFunctionCall(const TargetInfo &TI,
220*0fca6ea1SDimitry Andric unsigned BuiltinID,
221*0fca6ea1SDimitry Andric CallExpr *TheCall) {
222*0fca6ea1SDimitry Andric switch (BuiltinID) {
223*0fca6ea1SDimitry Andric case WebAssembly::BI__builtin_wasm_ref_null_extern:
224*0fca6ea1SDimitry Andric return BuiltinWasmRefNullExtern(TheCall);
225*0fca6ea1SDimitry Andric case WebAssembly::BI__builtin_wasm_ref_null_func:
226*0fca6ea1SDimitry Andric return BuiltinWasmRefNullFunc(TheCall);
227*0fca6ea1SDimitry Andric case WebAssembly::BI__builtin_wasm_table_get:
228*0fca6ea1SDimitry Andric return BuiltinWasmTableGet(TheCall);
229*0fca6ea1SDimitry Andric case WebAssembly::BI__builtin_wasm_table_set:
230*0fca6ea1SDimitry Andric return BuiltinWasmTableSet(TheCall);
231*0fca6ea1SDimitry Andric case WebAssembly::BI__builtin_wasm_table_size:
232*0fca6ea1SDimitry Andric return BuiltinWasmTableSize(TheCall);
233*0fca6ea1SDimitry Andric case WebAssembly::BI__builtin_wasm_table_grow:
234*0fca6ea1SDimitry Andric return BuiltinWasmTableGrow(TheCall);
235*0fca6ea1SDimitry Andric case WebAssembly::BI__builtin_wasm_table_fill:
236*0fca6ea1SDimitry Andric return BuiltinWasmTableFill(TheCall);
237*0fca6ea1SDimitry Andric case WebAssembly::BI__builtin_wasm_table_copy:
238*0fca6ea1SDimitry Andric return BuiltinWasmTableCopy(TheCall);
239*0fca6ea1SDimitry Andric }
240*0fca6ea1SDimitry Andric
241*0fca6ea1SDimitry Andric return false;
242*0fca6ea1SDimitry Andric }
243*0fca6ea1SDimitry Andric
244*0fca6ea1SDimitry Andric WebAssemblyImportModuleAttr *
mergeImportModuleAttr(Decl * D,const WebAssemblyImportModuleAttr & AL)245*0fca6ea1SDimitry Andric SemaWasm::mergeImportModuleAttr(Decl *D,
246*0fca6ea1SDimitry Andric const WebAssemblyImportModuleAttr &AL) {
247*0fca6ea1SDimitry Andric auto *FD = cast<FunctionDecl>(D);
248*0fca6ea1SDimitry Andric
249*0fca6ea1SDimitry Andric if (const auto *ExistingAttr = FD->getAttr<WebAssemblyImportModuleAttr>()) {
250*0fca6ea1SDimitry Andric if (ExistingAttr->getImportModule() == AL.getImportModule())
251*0fca6ea1SDimitry Andric return nullptr;
252*0fca6ea1SDimitry Andric Diag(ExistingAttr->getLocation(), diag::warn_mismatched_import)
253*0fca6ea1SDimitry Andric << 0 << ExistingAttr->getImportModule() << AL.getImportModule();
254*0fca6ea1SDimitry Andric Diag(AL.getLoc(), diag::note_previous_attribute);
255*0fca6ea1SDimitry Andric return nullptr;
256*0fca6ea1SDimitry Andric }
257*0fca6ea1SDimitry Andric if (FD->hasBody()) {
258*0fca6ea1SDimitry Andric Diag(AL.getLoc(), diag::warn_import_on_definition) << 0;
259*0fca6ea1SDimitry Andric return nullptr;
260*0fca6ea1SDimitry Andric }
261*0fca6ea1SDimitry Andric return ::new (getASTContext())
262*0fca6ea1SDimitry Andric WebAssemblyImportModuleAttr(getASTContext(), AL, AL.getImportModule());
263*0fca6ea1SDimitry Andric }
264*0fca6ea1SDimitry Andric
265*0fca6ea1SDimitry Andric WebAssemblyImportNameAttr *
mergeImportNameAttr(Decl * D,const WebAssemblyImportNameAttr & AL)266*0fca6ea1SDimitry Andric SemaWasm::mergeImportNameAttr(Decl *D, const WebAssemblyImportNameAttr &AL) {
267*0fca6ea1SDimitry Andric auto *FD = cast<FunctionDecl>(D);
268*0fca6ea1SDimitry Andric
269*0fca6ea1SDimitry Andric if (const auto *ExistingAttr = FD->getAttr<WebAssemblyImportNameAttr>()) {
270*0fca6ea1SDimitry Andric if (ExistingAttr->getImportName() == AL.getImportName())
271*0fca6ea1SDimitry Andric return nullptr;
272*0fca6ea1SDimitry Andric Diag(ExistingAttr->getLocation(), diag::warn_mismatched_import)
273*0fca6ea1SDimitry Andric << 1 << ExistingAttr->getImportName() << AL.getImportName();
274*0fca6ea1SDimitry Andric Diag(AL.getLoc(), diag::note_previous_attribute);
275*0fca6ea1SDimitry Andric return nullptr;
276*0fca6ea1SDimitry Andric }
277*0fca6ea1SDimitry Andric if (FD->hasBody()) {
278*0fca6ea1SDimitry Andric Diag(AL.getLoc(), diag::warn_import_on_definition) << 1;
279*0fca6ea1SDimitry Andric return nullptr;
280*0fca6ea1SDimitry Andric }
281*0fca6ea1SDimitry Andric return ::new (getASTContext())
282*0fca6ea1SDimitry Andric WebAssemblyImportNameAttr(getASTContext(), AL, AL.getImportName());
283*0fca6ea1SDimitry Andric }
284*0fca6ea1SDimitry Andric
handleWebAssemblyImportModuleAttr(Decl * D,const ParsedAttr & AL)285*0fca6ea1SDimitry Andric void SemaWasm::handleWebAssemblyImportModuleAttr(Decl *D,
286*0fca6ea1SDimitry Andric const ParsedAttr &AL) {
287*0fca6ea1SDimitry Andric auto *FD = cast<FunctionDecl>(D);
288*0fca6ea1SDimitry Andric
289*0fca6ea1SDimitry Andric StringRef Str;
290*0fca6ea1SDimitry Andric SourceLocation ArgLoc;
291*0fca6ea1SDimitry Andric if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
292*0fca6ea1SDimitry Andric return;
293*0fca6ea1SDimitry Andric if (FD->hasBody()) {
294*0fca6ea1SDimitry Andric Diag(AL.getLoc(), diag::warn_import_on_definition) << 0;
295*0fca6ea1SDimitry Andric return;
296*0fca6ea1SDimitry Andric }
297*0fca6ea1SDimitry Andric
298*0fca6ea1SDimitry Andric FD->addAttr(::new (getASTContext())
299*0fca6ea1SDimitry Andric WebAssemblyImportModuleAttr(getASTContext(), AL, Str));
300*0fca6ea1SDimitry Andric }
301*0fca6ea1SDimitry Andric
handleWebAssemblyImportNameAttr(Decl * D,const ParsedAttr & AL)302*0fca6ea1SDimitry Andric void SemaWasm::handleWebAssemblyImportNameAttr(Decl *D, const ParsedAttr &AL) {
303*0fca6ea1SDimitry Andric auto *FD = cast<FunctionDecl>(D);
304*0fca6ea1SDimitry Andric
305*0fca6ea1SDimitry Andric StringRef Str;
306*0fca6ea1SDimitry Andric SourceLocation ArgLoc;
307*0fca6ea1SDimitry Andric if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
308*0fca6ea1SDimitry Andric return;
309*0fca6ea1SDimitry Andric if (FD->hasBody()) {
310*0fca6ea1SDimitry Andric Diag(AL.getLoc(), diag::warn_import_on_definition) << 1;
311*0fca6ea1SDimitry Andric return;
312*0fca6ea1SDimitry Andric }
313*0fca6ea1SDimitry Andric
314*0fca6ea1SDimitry Andric FD->addAttr(::new (getASTContext())
315*0fca6ea1SDimitry Andric WebAssemblyImportNameAttr(getASTContext(), AL, Str));
316*0fca6ea1SDimitry Andric }
317*0fca6ea1SDimitry Andric
handleWebAssemblyExportNameAttr(Decl * D,const ParsedAttr & AL)318*0fca6ea1SDimitry Andric void SemaWasm::handleWebAssemblyExportNameAttr(Decl *D, const ParsedAttr &AL) {
319*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext();
320*0fca6ea1SDimitry Andric if (!isFuncOrMethodForAttrSubject(D)) {
321*0fca6ea1SDimitry Andric Diag(D->getLocation(), diag::warn_attribute_wrong_decl_type)
322*0fca6ea1SDimitry Andric << AL << AL.isRegularKeywordAttribute() << ExpectedFunction;
323*0fca6ea1SDimitry Andric return;
324*0fca6ea1SDimitry Andric }
325*0fca6ea1SDimitry Andric
326*0fca6ea1SDimitry Andric auto *FD = cast<FunctionDecl>(D);
327*0fca6ea1SDimitry Andric if (FD->isThisDeclarationADefinition()) {
328*0fca6ea1SDimitry Andric Diag(D->getLocation(), diag::err_alias_is_definition) << FD << 0;
329*0fca6ea1SDimitry Andric return;
330*0fca6ea1SDimitry Andric }
331*0fca6ea1SDimitry Andric
332*0fca6ea1SDimitry Andric StringRef Str;
333*0fca6ea1SDimitry Andric SourceLocation ArgLoc;
334*0fca6ea1SDimitry Andric if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &ArgLoc))
335*0fca6ea1SDimitry Andric return;
336*0fca6ea1SDimitry Andric
337*0fca6ea1SDimitry Andric D->addAttr(::new (Context) WebAssemblyExportNameAttr(Context, AL, Str));
338*0fca6ea1SDimitry Andric D->addAttr(UsedAttr::CreateImplicit(Context));
339*0fca6ea1SDimitry Andric }
340*0fca6ea1SDimitry Andric
341*0fca6ea1SDimitry Andric } // namespace clang
342