1 //===- Module.cpp - Describe a module -------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines the Module class, which describes a module in the source
12 //===----------------------------------------------------------------------===//
14 #include "clang/Basic/Module.h"
15 #include "clang/Basic/CharInfo.h"
16 #include "clang/Basic/FileManager.h"
17 #include "clang/Basic/LangOptions.h"
18 #include "clang/Basic/SourceLocation.h"
19 #include "clang/Basic/TargetInfo.h"
20 #include "llvm/ADT/ArrayRef.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/ADT/StringMap.h"
23 #include "llvm/ADT/StringRef.h"
24 #include "llvm/ADT/StringSwitch.h"
25 #include "llvm/Support/Compiler.h"
26 #include "llvm/Support/ErrorHandling.h"
27 #include "llvm/Support/raw_ostream.h"
35 using namespace clang
;
37 Module::Module(StringRef Name
, SourceLocation DefinitionLoc
, Module
*Parent
,
38 bool IsFramework
, bool IsExplicit
, unsigned VisibilityID
)
39 : Name(Name
), DefinitionLoc(DefinitionLoc
), Parent(Parent
),
40 VisibilityID(VisibilityID
), IsUnimportable(false),
41 HasIncompatibleModuleFile(false), IsAvailable(true),
42 IsFromModuleFile(false), IsFramework(IsFramework
), IsExplicit(IsExplicit
),
43 IsSystem(false), IsExternC(false), IsInferred(false),
44 InferSubmodules(false), InferExplicitSubmodules(false),
45 InferExportWildcard(false), ConfigMacrosExhaustive(false),
46 NoUndeclaredIncludes(false), ModuleMapIsPrivate(false),
47 NamedModuleHasInit(true), NameVisibility(Hidden
) {
49 IsAvailable
= Parent
->isAvailable();
50 IsUnimportable
= Parent
->isUnimportable();
51 IsSystem
= Parent
->IsSystem
;
52 IsExternC
= Parent
->IsExternC
;
53 NoUndeclaredIncludes
= Parent
->NoUndeclaredIncludes
;
54 ModuleMapIsPrivate
= Parent
->ModuleMapIsPrivate
;
56 Parent
->SubModuleIndex
[Name
] = Parent
->SubModules
.size();
57 Parent
->SubModules
.push_back(this);
62 for (auto *Submodule
: SubModules
) {
67 static bool isPlatformEnvironment(const TargetInfo
&Target
, StringRef Feature
) {
68 StringRef Platform
= Target
.getPlatformName();
69 StringRef Env
= Target
.getTriple().getEnvironmentName();
71 // Attempt to match platform and environment.
72 if (Platform
== Feature
|| Target
.getTriple().getOSName() == Feature
||
76 auto CmpPlatformEnv
= [](StringRef LHS
, StringRef RHS
) {
77 auto Pos
= LHS
.find('-');
78 if (Pos
== StringRef::npos
)
80 SmallString
<128> NewLHS
= LHS
.slice(0, Pos
);
81 NewLHS
+= LHS
.slice(Pos
+1, LHS
.size());
85 SmallString
<128> PlatformEnv
= Target
.getTriple().getOSAndEnvironmentName();
86 // Darwin has different but equivalent variants for simulators, example:
87 // 1. x86_64-apple-ios-simulator
88 // 2. x86_64-apple-iossimulator
89 // where both are valid examples of the same platform+environment but in the
90 // variant (2) the simulator is hardcoded as part of the platform name. Both
91 // forms above should match for "iossimulator" requirement.
92 if (Target
.getTriple().isOSDarwin() && PlatformEnv
.endswith("simulator"))
93 return PlatformEnv
== Feature
|| CmpPlatformEnv(PlatformEnv
, Feature
);
95 return PlatformEnv
== Feature
;
98 /// Determine whether a translation unit built using the current
99 /// language options has the given feature.
100 static bool hasFeature(StringRef Feature
, const LangOptions
&LangOpts
,
101 const TargetInfo
&Target
) {
102 bool HasFeature
= llvm::StringSwitch
<bool>(Feature
)
103 .Case("altivec", LangOpts
.AltiVec
)
104 .Case("blocks", LangOpts
.Blocks
)
105 .Case("coroutines", LangOpts
.Coroutines
)
106 .Case("cplusplus", LangOpts
.CPlusPlus
)
107 .Case("cplusplus11", LangOpts
.CPlusPlus11
)
108 .Case("cplusplus14", LangOpts
.CPlusPlus14
)
109 .Case("cplusplus17", LangOpts
.CPlusPlus17
)
110 .Case("cplusplus20", LangOpts
.CPlusPlus20
)
111 .Case("cplusplus23", LangOpts
.CPlusPlus23
)
112 .Case("cplusplus26", LangOpts
.CPlusPlus26
)
113 .Case("c99", LangOpts
.C99
)
114 .Case("c11", LangOpts
.C11
)
115 .Case("c17", LangOpts
.C17
)
116 .Case("c23", LangOpts
.C23
)
117 .Case("freestanding", LangOpts
.Freestanding
)
118 .Case("gnuinlineasm", LangOpts
.GNUAsm
)
119 .Case("objc", LangOpts
.ObjC
)
120 .Case("objc_arc", LangOpts
.ObjCAutoRefCount
)
121 .Case("opencl", LangOpts
.OpenCL
)
122 .Case("tls", Target
.isTLSSupported())
123 .Case("zvector", LangOpts
.ZVector
)
124 .Default(Target
.hasFeature(Feature
) ||
125 isPlatformEnvironment(Target
, Feature
));
127 HasFeature
= llvm::is_contained(LangOpts
.ModuleFeatures
, Feature
);
131 bool Module::isUnimportable(const LangOptions
&LangOpts
,
132 const TargetInfo
&Target
, Requirement
&Req
,
133 Module
*&ShadowingModule
) const {
137 for (const Module
*Current
= this; Current
; Current
= Current
->Parent
) {
138 if (Current
->ShadowingModule
) {
139 ShadowingModule
= Current
->ShadowingModule
;
142 for (unsigned I
= 0, N
= Current
->Requirements
.size(); I
!= N
; ++I
) {
143 if (hasFeature(Current
->Requirements
[I
].first
, LangOpts
, Target
) !=
144 Current
->Requirements
[I
].second
) {
145 Req
= Current
->Requirements
[I
];
151 llvm_unreachable("could not find a reason why module is unimportable");
154 // The -fmodule-name option tells the compiler to textually include headers in
155 // the specified module, meaning Clang won't build the specified module. This
156 // is useful in a number of situations, for instance, when building a library
157 // that vends a module map, one might want to avoid hitting intermediate build
158 // products containing the module map or avoid finding the system installed
159 // modulemap for that library.
160 bool Module::isForBuilding(const LangOptions
&LangOpts
) const {
161 StringRef TopLevelName
= getTopLevelModuleName();
162 StringRef CurrentModule
= LangOpts
.CurrentModule
;
164 // When building the implementation of framework Foo, we want to make sure
165 // that Foo *and* Foo_Private are textually included and no modules are built
167 if (!LangOpts
.isCompilingModule() && getTopLevelModule()->IsFramework
&&
168 CurrentModule
== LangOpts
.ModuleName
&&
169 !CurrentModule
.endswith("_Private") && TopLevelName
.endswith("_Private"))
170 TopLevelName
= TopLevelName
.drop_back(8);
172 return TopLevelName
== CurrentModule
;
175 bool Module::isAvailable(const LangOptions
&LangOpts
, const TargetInfo
&Target
,
177 UnresolvedHeaderDirective
&MissingHeader
,
178 Module
*&ShadowingModule
) const {
182 if (isUnimportable(LangOpts
, Target
, Req
, ShadowingModule
))
185 // FIXME: All missing headers are listed on the top-level module. Should we
187 for (const Module
*Current
= this; Current
; Current
= Current
->Parent
) {
188 if (!Current
->MissingHeaders
.empty()) {
189 MissingHeader
= Current
->MissingHeaders
.front();
194 llvm_unreachable("could not find a reason why module is unavailable");
197 bool Module::isSubModuleOf(const Module
*Other
) const {
198 for (auto *Parent
= this; Parent
; Parent
= Parent
->Parent
) {
205 const Module
*Module::getTopLevelModule() const {
206 const Module
*Result
= this;
207 while (Result
->Parent
)
208 Result
= Result
->Parent
;
213 static StringRef
getModuleNameFromComponent(
214 const std::pair
<std::string
, SourceLocation
> &IdComponent
) {
215 return IdComponent
.first
;
218 static StringRef
getModuleNameFromComponent(StringRef R
) { return R
; }
220 template<typename InputIter
>
221 static void printModuleId(raw_ostream
&OS
, InputIter Begin
, InputIter End
,
222 bool AllowStringLiterals
= true) {
223 for (InputIter It
= Begin
; It
!= End
; ++It
) {
227 StringRef Name
= getModuleNameFromComponent(*It
);
228 if (!AllowStringLiterals
|| isValidAsciiIdentifier(Name
))
232 OS
.write_escaped(Name
);
238 template<typename Container
>
239 static void printModuleId(raw_ostream
&OS
, const Container
&C
) {
240 return printModuleId(OS
, C
.begin(), C
.end());
243 std::string
Module::getFullModuleName(bool AllowStringLiterals
) const {
244 SmallVector
<StringRef
, 2> Names
;
246 // Build up the set of module names (from innermost to outermost).
247 for (const Module
*M
= this; M
; M
= M
->Parent
)
248 Names
.push_back(M
->Name
);
252 llvm::raw_string_ostream
Out(Result
);
253 printModuleId(Out
, Names
.rbegin(), Names
.rend(), AllowStringLiterals
);
259 bool Module::fullModuleNameIs(ArrayRef
<StringRef
> nameParts
) const {
260 for (const Module
*M
= this; M
; M
= M
->Parent
) {
261 if (nameParts
.empty() || M
->Name
!= nameParts
.back())
263 nameParts
= nameParts
.drop_back();
265 return nameParts
.empty();
268 OptionalDirectoryEntryRef
Module::getEffectiveUmbrellaDir() const {
269 if (const auto *Hdr
= std::get_if
<FileEntryRef
>(&Umbrella
))
270 return Hdr
->getDir();
271 if (const auto *Dir
= std::get_if
<DirectoryEntryRef
>(&Umbrella
))
276 void Module::addTopHeader(FileEntryRef File
) {
278 TopHeaders
.insert(File
);
281 ArrayRef
<FileEntryRef
> Module::getTopHeaders(FileManager
&FileMgr
) {
282 if (!TopHeaderNames
.empty()) {
283 for (StringRef TopHeaderName
: TopHeaderNames
)
284 if (auto FE
= FileMgr
.getOptionalFileRef(TopHeaderName
))
285 TopHeaders
.insert(*FE
);
286 TopHeaderNames
.clear();
289 return llvm::ArrayRef(TopHeaders
.begin(), TopHeaders
.end());
292 bool Module::directlyUses(const Module
*Requested
) {
293 auto *Top
= getTopLevelModule();
295 // A top-level module implicitly uses itself.
296 if (Requested
->isSubModuleOf(Top
))
299 for (auto *Use
: Top
->DirectUses
)
300 if (Requested
->isSubModuleOf(Use
))
303 // Anyone is allowed to use our builtin stdarg.h and stddef.h and their
304 // accompanying modules.
305 if (Requested
->getTopLevelModuleName() == "_Builtin_stdarg" ||
306 Requested
->getTopLevelModuleName() == "_Builtin_stddef")
309 if (NoUndeclaredIncludes
)
310 UndeclaredUses
.insert(Requested
);
315 void Module::addRequirement(StringRef Feature
, bool RequiredState
,
316 const LangOptions
&LangOpts
,
317 const TargetInfo
&Target
) {
318 Requirements
.push_back(Requirement(std::string(Feature
), RequiredState
));
320 // If this feature is currently available, we're done.
321 if (hasFeature(Feature
, LangOpts
, Target
) == RequiredState
)
324 markUnavailable(/*Unimportable*/true);
327 void Module::markUnavailable(bool Unimportable
) {
328 auto needUpdate
= [Unimportable
](Module
*M
) {
329 return M
->IsAvailable
|| (!M
->IsUnimportable
&& Unimportable
);
332 if (!needUpdate(this))
335 SmallVector
<Module
*, 2> Stack
;
336 Stack
.push_back(this);
337 while (!Stack
.empty()) {
338 Module
*Current
= Stack
.back();
341 if (!needUpdate(Current
))
344 Current
->IsAvailable
= false;
345 Current
->IsUnimportable
|= Unimportable
;
346 for (auto *Submodule
: Current
->submodules()) {
347 if (needUpdate(Submodule
))
348 Stack
.push_back(Submodule
);
353 Module
*Module::findSubmodule(StringRef Name
) const {
354 llvm::StringMap
<unsigned>::const_iterator Pos
= SubModuleIndex
.find(Name
);
355 if (Pos
== SubModuleIndex
.end())
358 return SubModules
[Pos
->getValue()];
361 Module
*Module::findOrInferSubmodule(StringRef Name
) {
362 llvm::StringMap
<unsigned>::const_iterator Pos
= SubModuleIndex
.find(Name
);
363 if (Pos
!= SubModuleIndex
.end())
364 return SubModules
[Pos
->getValue()];
365 if (!InferSubmodules
)
367 Module
*Result
= new Module(Name
, SourceLocation(), this, false, InferExplicitSubmodules
, 0);
368 Result
->InferExplicitSubmodules
= InferExplicitSubmodules
;
369 Result
->InferSubmodules
= InferSubmodules
;
370 Result
->InferExportWildcard
= InferExportWildcard
;
371 if (Result
->InferExportWildcard
)
372 Result
->Exports
.push_back(Module::ExportDecl(nullptr, true));
376 Module
*Module::getGlobalModuleFragment() const {
377 assert(isNamedModuleUnit() && "We should only query the global module "
378 "fragment from the C++ 20 Named modules");
380 for (auto *SubModule
: SubModules
)
381 if (SubModule
->isExplicitGlobalModule())
387 Module
*Module::getPrivateModuleFragment() const {
388 assert(isNamedModuleUnit() && "We should only query the private module "
389 "fragment from the C++ 20 Named modules");
391 for (auto *SubModule
: SubModules
)
392 if (SubModule
->isPrivateModule())
398 void Module::getExportedModules(SmallVectorImpl
<Module
*> &Exported
) const {
399 // All non-explicit submodules are exported.
400 for (std::vector
<Module
*>::const_iterator I
= SubModules
.begin(),
401 E
= SubModules
.end();
404 if (!Mod
->IsExplicit
)
405 Exported
.push_back(Mod
);
408 // Find re-exported modules by filtering the list of imported modules.
409 bool AnyWildcard
= false;
410 bool UnrestrictedWildcard
= false;
411 SmallVector
<Module
*, 4> WildcardRestrictions
;
412 for (unsigned I
= 0, N
= Exports
.size(); I
!= N
; ++I
) {
413 Module
*Mod
= Exports
[I
].getPointer();
414 if (!Exports
[I
].getInt()) {
415 // Export a named module directly; no wildcards involved.
416 Exported
.push_back(Mod
);
421 // Wildcard export: export all of the imported modules that match
422 // the given pattern.
424 if (UnrestrictedWildcard
)
427 if (Module
*Restriction
= Exports
[I
].getPointer())
428 WildcardRestrictions
.push_back(Restriction
);
430 WildcardRestrictions
.clear();
431 UnrestrictedWildcard
= true;
435 // If there were any wildcards, push any imported modules that were
436 // re-exported by the wildcard restriction.
440 for (unsigned I
= 0, N
= Imports
.size(); I
!= N
; ++I
) {
441 Module
*Mod
= Imports
[I
];
442 bool Acceptable
= UnrestrictedWildcard
;
444 // Check whether this module meets one of the restrictions.
445 for (unsigned R
= 0, NR
= WildcardRestrictions
.size(); R
!= NR
; ++R
) {
446 Module
*Restriction
= WildcardRestrictions
[R
];
447 if (Mod
== Restriction
|| Mod
->isSubModuleOf(Restriction
)) {
457 Exported
.push_back(Mod
);
461 void Module::buildVisibleModulesCache() const {
462 assert(VisibleModulesCache
.empty() && "cache does not need building");
464 // This module is visible to itself.
465 VisibleModulesCache
.insert(this);
467 // Every imported module is visible.
468 SmallVector
<Module
*, 16> Stack(Imports
.begin(), Imports
.end());
469 while (!Stack
.empty()) {
470 Module
*CurrModule
= Stack
.pop_back_val();
472 // Every module transitively exported by an imported module is visible.
473 if (VisibleModulesCache
.insert(CurrModule
).second
)
474 CurrModule
->getExportedModules(Stack
);
478 void Module::print(raw_ostream
&OS
, unsigned Indent
, bool Dump
) const {
485 printModuleId(OS
, &Name
, &Name
+ 1);
487 if (IsSystem
|| IsExternC
) {
488 OS
.indent(Indent
+ 2);
497 if (!Requirements
.empty()) {
498 OS
.indent(Indent
+ 2);
500 for (unsigned I
= 0, N
= Requirements
.size(); I
!= N
; ++I
) {
503 if (!Requirements
[I
].second
)
505 OS
<< Requirements
[I
].first
;
510 if (std::optional
<Header
> H
= getUmbrellaHeaderAsWritten()) {
511 OS
.indent(Indent
+ 2);
512 OS
<< "umbrella header \"";
513 OS
.write_escaped(H
->NameAsWritten
);
515 } else if (std::optional
<DirectoryName
> D
= getUmbrellaDirAsWritten()) {
516 OS
.indent(Indent
+ 2);
518 OS
.write_escaped(D
->NameAsWritten
);
522 if (!ConfigMacros
.empty() || ConfigMacrosExhaustive
) {
523 OS
.indent(Indent
+ 2);
524 OS
<< "config_macros ";
525 if (ConfigMacrosExhaustive
)
526 OS
<< "[exhaustive]";
527 for (unsigned I
= 0, N
= ConfigMacros
.size(); I
!= N
; ++I
) {
530 OS
<< ConfigMacros
[I
];
538 } Kinds
[] = {{"", HK_Normal
},
539 {"textual ", HK_Textual
},
540 {"private ", HK_Private
},
541 {"private textual ", HK_PrivateTextual
},
542 {"exclude ", HK_Excluded
}};
544 for (auto &K
: Kinds
) {
545 assert(&K
== &Kinds
[K
.Kind
] && "kinds in wrong order");
546 for (auto &H
: Headers
[K
.Kind
]) {
547 OS
.indent(Indent
+ 2);
548 OS
<< K
.Prefix
<< "header \"";
549 OS
.write_escaped(H
.NameAsWritten
);
550 OS
<< "\" { size " << H
.Entry
.getSize()
551 << " mtime " << H
.Entry
.getModificationTime() << " }\n";
554 for (auto *Unresolved
: {&UnresolvedHeaders
, &MissingHeaders
}) {
555 for (auto &U
: *Unresolved
) {
556 OS
.indent(Indent
+ 2);
557 OS
<< Kinds
[U
.Kind
].Prefix
<< "header \"";
558 OS
.write_escaped(U
.FileName
);
560 if (U
.Size
|| U
.ModTime
) {
563 OS
<< " size " << *U
.Size
;
565 OS
<< " mtime " << *U
.ModTime
;
572 if (!ExportAsModule
.empty()) {
573 OS
.indent(Indent
+ 2);
574 OS
<< "export_as" << ExportAsModule
<< "\n";
577 for (auto *Submodule
: submodules())
578 // Print inferred subframework modules so that we don't need to re-infer
579 // them (requires expensive directory iteration + stat calls) when we build
580 // the module. Regular inferred submodules are OK, as we need to look at all
581 // those header files anyway.
582 if (!Submodule
->IsInferred
|| Submodule
->IsFramework
)
583 Submodule
->print(OS
, Indent
+ 2, Dump
);
585 for (unsigned I
= 0, N
= Exports
.size(); I
!= N
; ++I
) {
586 OS
.indent(Indent
+ 2);
588 if (Module
*Restriction
= Exports
[I
].getPointer()) {
589 OS
<< Restriction
->getFullModuleName(true);
590 if (Exports
[I
].getInt())
598 for (unsigned I
= 0, N
= UnresolvedExports
.size(); I
!= N
; ++I
) {
599 OS
.indent(Indent
+ 2);
601 printModuleId(OS
, UnresolvedExports
[I
].Id
);
602 if (UnresolvedExports
[I
].Wildcard
)
603 OS
<< (UnresolvedExports
[I
].Id
.empty() ? "*" : ".*");
608 for (Module
*M
: Imports
) {
609 OS
.indent(Indent
+ 2);
610 llvm::errs() << "import " << M
->getFullModuleName() << "\n";
614 for (unsigned I
= 0, N
= DirectUses
.size(); I
!= N
; ++I
) {
615 OS
.indent(Indent
+ 2);
617 OS
<< DirectUses
[I
]->getFullModuleName(true);
621 for (unsigned I
= 0, N
= UnresolvedDirectUses
.size(); I
!= N
; ++I
) {
622 OS
.indent(Indent
+ 2);
624 printModuleId(OS
, UnresolvedDirectUses
[I
]);
628 for (unsigned I
= 0, N
= LinkLibraries
.size(); I
!= N
; ++I
) {
629 OS
.indent(Indent
+ 2);
631 if (LinkLibraries
[I
].IsFramework
)
634 OS
.write_escaped(LinkLibraries
[I
].Library
);
638 for (unsigned I
= 0, N
= UnresolvedConflicts
.size(); I
!= N
; ++I
) {
639 OS
.indent(Indent
+ 2);
641 printModuleId(OS
, UnresolvedConflicts
[I
].Id
);
643 OS
.write_escaped(UnresolvedConflicts
[I
].Message
);
647 for (unsigned I
= 0, N
= Conflicts
.size(); I
!= N
; ++I
) {
648 OS
.indent(Indent
+ 2);
650 OS
<< Conflicts
[I
].Other
->getFullModuleName(true);
652 OS
.write_escaped(Conflicts
[I
].Message
);
656 if (InferSubmodules
) {
657 OS
.indent(Indent
+ 2);
658 if (InferExplicitSubmodules
)
660 OS
<< "module * {\n";
661 if (InferExportWildcard
) {
662 OS
.indent(Indent
+ 4);
665 OS
.indent(Indent
+ 2);
673 LLVM_DUMP_METHOD
void Module::dump() const {
674 print(llvm::errs(), 0, true);
677 void VisibleModuleSet::setVisible(Module
*M
, SourceLocation Loc
,
678 VisibleCallback Vis
, ConflictCallback Cb
) {
679 // We can't import a global module fragment so the location can be invalid.
680 assert((M
->isGlobalModule() || Loc
.isValid()) &&
681 "setVisible expects a valid import location");
689 Visiting
*ExportedBy
;
692 std::function
<void(Visiting
)> VisitModule
= [&](Visiting V
) {
693 // Nothing to do for a module that's already visible.
694 unsigned ID
= V
.M
->getVisibilityID();
695 if (ImportLocs
.size() <= ID
)
696 ImportLocs
.resize(ID
+ 1);
697 else if (ImportLocs
[ID
].isValid())
700 ImportLocs
[ID
] = Loc
;
703 // Make any exported modules visible.
704 SmallVector
<Module
*, 16> Exports
;
705 V
.M
->getExportedModules(Exports
);
706 for (Module
*E
: Exports
) {
707 // Don't import non-importable modules.
708 if (!E
->isUnimportable())
709 VisitModule({E
, &V
});
712 for (auto &C
: V
.M
->Conflicts
) {
713 if (isVisible(C
.Other
)) {
714 llvm::SmallVector
<Module
*, 8> Path
;
715 for (Visiting
*I
= &V
; I
; I
= I
->ExportedBy
)
716 Path
.push_back(I
->M
);
717 Cb(Path
, C
.Other
, C
.Message
);
721 VisitModule({M
, nullptr});
724 void VisibleModuleSet::makeTransitiveImportsVisible(Module
*M
,
727 ConflictCallback Cb
) {
728 for (auto *I
: M
->Imports
)
729 setVisible(I
, Loc
, Vis
, Cb
);
732 ASTSourceDescriptor::ASTSourceDescriptor(Module
&M
)
733 : Signature(M
.Signature
), ClangModule(&M
) {
735 Path
= M
.Directory
->getName();
736 if (auto File
= M
.getASTFile())
737 ASTFile
= File
->getName();
740 std::string
ASTSourceDescriptor::getModuleName() const {
742 return ClangModule
->Name
;
744 return std::string(PCHModuleName
);