ParsedTemplate.h revision e4b92761b43ced611c417ae478568610f1ad7b1e
1b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project//===--- ParsedTemplate.h - Template Parsing Data Types -------------------===// 2b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project// 3b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project// The LLVM Compiler Infrastructure 4b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project// 5b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project// This file is distributed under the University of Illinois Open Source 6b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project// License. See LICENSE.TXT for details. 7b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project// 8b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project//===----------------------------------------------------------------------===// 9b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project// 10b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project// This file provides data structures that store the parsed representation of 11b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project// templates. 12b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project// 13b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project//===----------------------------------------------------------------------===// 14b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project#ifndef LLVM_CLANG_SEMA_PARSEDTEMPLATE_H 15b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project#define LLVM_CLANG_SEMA_PARSEDTEMPLATE_H 16b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 17b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project#include "clang/Sema/DeclSpec.h" 18b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project#include "clang/Sema/Ownership.h" 191efb18228a45952d699af280482e1c51a4582690Owen Lin#include <cassert> 2059ddc8c1add2fcffe523e3877baad1b6cc5ba2fbChung-yih Wang 211b6cd72127f64a5306ee4acecaf6113627d35db2Wu-cheng Linamespace clang { 22937ea10204656beaa848df913dc9cb9b5a9b934fWu-cheng Li /// \brief Represents the parsed form of a C++ template argument. 23937ea10204656beaa848df913dc9cb9b5a9b934fWu-cheng Li class ParsedTemplateArgument { 247341b9b5d8194c4ab7140977a8c5218e6d83d516Wu-cheng Li public: 256fb969e2edd99340b3b77eae4e7b313a82937930Andy Stadler /// \brief Describes the kind of template argument that was parsed. 26c5e37cbb96b8284203560c51dd5f41c705a21f58Wu-cheng Li enum KindType { 271efb18228a45952d699af280482e1c51a4582690Owen Lin /// \brief A template type parameter, stored as a type. 287f0d458b7d2ed913879db247d16abcfdec0dc897Wu-cheng Li Type, 291efb18228a45952d699af280482e1c51a4582690Owen Lin /// \brief A non-type template parameter, stored as an expression. 30b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project NonType, 31b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /// \brief A template template argument, stored as a template name. 326d68a36b5da24f70e1a8d5e9529720eeb8ce6d86Ray Chen Template 33b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project }; 34b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 35b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /// \brief Build an empty template argument. 36b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /// 3759b5974a4ae078eb7628fd855db89e5be9b0fe6fOwen Lin /// This template argument is invalid. 38f00d421845b4ff2eca1354419889886fec5f2538Owen Lin ParsedTemplateArgument() : Kind(Type), Arg(0) { } 39b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 4018c1ad898f3fddcd321af7ffbb32416a1b32f323Wu-cheng Li /// \brief Create a template type argument or non-type template argument. 417895ae7d31da363a225988ffd2e0479fece6499eWu-cheng Li /// 424aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li /// \param Arg the template type argument or non-type template argument. 434305c70dc849156be5d79d52772ea71cd890ca40Wu-cheng Li /// \param Loc the location of the type. 44b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation Loc) 454305c70dc849156be5d79d52772ea71cd890ca40Wu-cheng Li : Kind(Kind), Arg(Arg), Loc(Loc) { } 46b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 47b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /// \brief Create a template template argument. 48b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /// 49b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /// \param SS the C++ scope specifier that precedes the template name, if 5002af7e82f97ade581703c7f4a32666e4f578173bWu-cheng Li /// any. 51281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin /// 52b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /// \param Template the template to which this template template 53b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /// argument refers. 54b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /// 55cdf69cba3617c446e4fe9a92b4b4199c6ed36d01Owen Lin /// \param TemplateLoc the location of the template name. 56b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project ParsedTemplateArgument(const CXXScopeSpec &SS, 57f86e6af0b8833f5f8a4b03fefba54b1922280d28Chih-Chung Chang ParsedTemplateTy Template, 58232700d54651dcaefb378dc22bdb008a9815d1cdWu-cheng Li SourceLocation TemplateLoc) 59b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project : Kind(ParsedTemplateArgument::Template), 60ed32015f4a0536e842306a207d620ec5e3f665c0Owen Lin Arg(Template.getAsOpaquePtr()), 61b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project Loc(TemplateLoc), SS(SS), EllipsisLoc() { } 62aa3cc2012a1ee0cc04e1244dd977cb8bb84683e4Wu-cheng Li 63c5e37cbb96b8284203560c51dd5f41c705a21f58Wu-cheng Li /// \brief Determine whether the given template argument is invalid. 64b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project bool isInvalid() const { return Arg == 0; } 65b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 66b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /// \brief Determine what kind of template argument we have. 676fb969e2edd99340b3b77eae4e7b313a82937930Andy Stadler KindType getKind() const { return Kind; } 6895fc5b2c5b14bb81332570f6d74f75cd63ea04b5Wu-cheng Li 69b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /// \brief Retrieve the template type argument's type. 70b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project ParsedType getAsType() const { 71ffcca7403c9a364403357d3c76a3ff256c63c786Cheng-Ru Lin assert(Kind == Type && "Not a template type argument"); 72b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return ParsedType::getFromOpaquePtr(Arg); 73b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 74b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 75b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /// \brief Retrieve the non-type template argument's expression. 76373d10b91c8e736275a0bc52e247598eec0b3ceaHung-ying Tyan Expr *getAsExpr() const { 7722e1d11ab2e59b672885fa5f7e5f08b1a2455225Wu-cheng Li assert(Kind == NonType && "Not a non-type template argument"); 78cd4aacd29f860ba6c1769372c698ab1a4517179cWu-cheng Li return static_cast<Expr*>(Arg); 79fba0439b62f19a2a19ff6559c1ae055e910400dbWu-cheng Li } 802e768c1b835a127f190395a91477144d8ae850acOwen Lin 810e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin /// \brief Retrieve the template template argument's template name. 820e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin ParsedTemplateTy getAsTemplate() const { 830e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin assert(Kind == Template && "Not a template template argument"); 840e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin return ParsedTemplateTy::getFromOpaquePtr(Arg); 850e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin } 8630055f6830b3d524cfbdfeab6536bb46e390747aPetri Gynther 870e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin /// \brief Retrieve the location of the template argument. 88cc5a6356055dd8a8a4017b0af5410b53f25aaef0Wu-cheng Li SourceLocation getLocation() const { return Loc; } 8930055f6830b3d524cfbdfeab6536bb46e390747aPetri Gynther 9082544b4564c079ece1a9065d19add36b2635bb8fOwen Lin /// \brief Retrieve the nested-name-specifier that precedes the template 910e841fe509c3b61ced7ddf4bee4728b382eae62fOwen Lin /// name in a template template argument. 92271b3095b9f763421c0547109da9de774795072dChih-Chung Chang const CXXScopeSpec &getScopeSpec() const { 937673ada94b5e2263e7190ca246694cdee31ed03eWu-cheng Li assert(Kind == Template && 9422e1d11ab2e59b672885fa5f7e5f08b1a2455225Wu-cheng Li "Only template template arguments can have a scope specifier"); 9522e1d11ab2e59b672885fa5f7e5f08b1a2455225Wu-cheng Li return SS; 96b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 97b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 98b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /// \brief Retrieve the location of the ellipsis that makes a template 998ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li /// template argument into a pack expansion. 1000aaed976b603c56006213d196e6b0703285dafd5Chia-chi Yeh SourceLocation getEllipsisLoc() const { 101b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project assert(Kind == Template && 102e43adb123b34432b977f57943c3c42614ccfd985Wu-cheng Li "Only template template arguments can have an ellipsis"); 103b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return EllipsisLoc; 104b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project } 1051de0469fa91cee8ed0771d020042cc82576a601cChih-Chung Chang 106232700d54651dcaefb378dc22bdb008a9815d1cdWu-cheng Li /// \brief Retrieve a pack expansion of the given template template 107551ce8ef001669d5e04359ab57c365082f75a905Wu-cheng Li /// argument. 108b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /// 109ee1cf3f0509987e9c76626077bd8117399311cedChih-Chung Chang /// \param EllipsisLoc The location of the ellipsis. 110ee1cf3f0509987e9c76626077bd8117399311cedChih-Chung Chang ParsedTemplateArgument getTemplatePackExpansion( 111ee1cf3f0509987e9c76626077bd8117399311cedChih-Chung Chang SourceLocation EllipsisLoc) const; 112ee1cf3f0509987e9c76626077bd8117399311cedChih-Chung Chang 113ee1cf3f0509987e9c76626077bd8117399311cedChih-Chung Chang private: 114ee1cf3f0509987e9c76626077bd8117399311cedChih-Chung Chang KindType Kind; 115ee1cf3f0509987e9c76626077bd8117399311cedChih-Chung Chang 116ee1cf3f0509987e9c76626077bd8117399311cedChih-Chung Chang /// \brief The actual template argument representation, which may be 117ee1cf3f0509987e9c76626077bd8117399311cedChih-Chung Chang /// an \c ActionBase::TypeTy* (for a type), an Expr* (for an 118ee1cf3f0509987e9c76626077bd8117399311cedChih-Chung Chang /// expression), or an ActionBase::TemplateTy (for a template). 119ed32015f4a0536e842306a207d620ec5e3f665c0Owen Lin void *Arg; 120ed32015f4a0536e842306a207d620ec5e3f665c0Owen Lin 121ed32015f4a0536e842306a207d620ec5e3f665c0Owen Lin /// \brief the location of the template argument. 122ed32015f4a0536e842306a207d620ec5e3f665c0Owen Lin SourceLocation Loc; 123b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 124b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /// \brief The nested-name-specifier that can accompany a template template 125b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /// argument. 12633be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin CXXScopeSpec SS; 12733be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin 12833be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin /// \brief The ellipsis location that can accompany a template template 12933be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin /// argument (turning it into a template template argument expansion). 13033be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin SourceLocation EllipsisLoc; 131316af30d026dd182edb482ef6de7a330d6b1b012Wu-cheng Li }; 132316af30d026dd182edb482ef6de7a330d6b1b012Wu-cheng Li 133316af30d026dd182edb482ef6de7a330d6b1b012Wu-cheng Li /// \brief Information about a template-id annotation 13433be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin /// token. 135c5019f4d58412da6227b3f2e6461bba5b7c671a3Wu-cheng Li /// 13635bda2dc8ab95a7baf68b544cf97826aabff6210Wu-cheng Li /// A template-id annotation token contains the template declaration, 1375f6484a74fe019337e436e6e0dcb07375a74af25President Li /// template arguments, whether those template arguments were types, 13870fe12f4d0ba9c08be9e0f0bda75b172a21cf70aOwen Lin /// expressions, or template names, and the source locations for important 1395f6484a74fe019337e436e6e0dcb07375a74af25President Li /// tokens. All of the information about template arguments is allocated 1404aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li /// directly after this structure. 141c5e37cbb96b8284203560c51dd5f41c705a21f58Wu-cheng Li struct TemplateIdAnnotation { 1424aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li /// \brief The nested-name-specifier that precedes the template name. 143c5e37cbb96b8284203560c51dd5f41c705a21f58Wu-cheng Li CXXScopeSpec SS; 144c5e37cbb96b8284203560c51dd5f41c705a21f58Wu-cheng Li 1454aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li /// TemplateKWLoc - The location of the template keyword within the 1461ef634d277d550ed55b5b7089dfd56ed71815bd6Chih-Chung Chang /// source. 147b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project SourceLocation TemplateKWLoc; 148e239acc2185c5fb47b22a65f78ffa461e19f183cOwen Lin 149e239acc2185c5fb47b22a65f78ffa461e19f183cOwen Lin /// TemplateNameLoc - The location of the template name within the 150e239acc2185c5fb47b22a65f78ffa461e19f183cOwen Lin /// source. 151b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project SourceLocation TemplateNameLoc; 152b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 153b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project /// FIXME: Temporarily stores the name of a specialization 1546d68a36b5da24f70e1a8d5e9529720eeb8ce6d86Ray Chen IdentifierInfo *Name; 155b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project 15695fc5b2c5b14bb81332570f6d74f75cd63ea04b5Wu-cheng Li /// FIXME: Temporarily stores the overloaded operator kind. 15795fc5b2c5b14bb81332570f6d74f75cd63ea04b5Wu-cheng Li OverloadedOperatorKind Operator; 15802ec7c0880ded5863d73d6f173ef35ab5c888dcdWu-cheng Li 159eb1f0c8299d96bad9bb449ff9e13eff4b43272ccHung-ying Tyan /// The declaration of the template corresponding to the 16003eeea3750b6b540b735e0f4d5d6d76c128cbacbWu-cheng Li /// template-name. 161dfb6f208e3f5dd7d68bcaade644aa1d1f1f0a98fWu-cheng Li ParsedTemplateTy Template; 16295fc5b2c5b14bb81332570f6d74f75cd63ea04b5Wu-cheng Li 16322e1d11ab2e59b672885fa5f7e5f08b1a2455225Wu-cheng Li /// The kind of template that Template refers to. 16418c1ad898f3fddcd321af7ffbb32416a1b32f323Wu-cheng Li TemplateNameKind Kind; 16522e1d11ab2e59b672885fa5f7e5f08b1a2455225Wu-cheng Li 1667895ae7d31da363a225988ffd2e0479fece6499eWu-cheng Li /// The location of the '<' before the template argument 167551ce8ef001669d5e04359ab57c365082f75a905Wu-cheng Li /// list. 16822e1d11ab2e59b672885fa5f7e5f08b1a2455225Wu-cheng Li SourceLocation LAngleLoc; 169281be5337852cb4b5d24e0a0440c426cb96bbebdOwen Lin 1704de149ceb47f2c251f646419907424bfb67d2b64Owen Lin /// The location of the '>' after the template argument 171c5e37cbb96b8284203560c51dd5f41c705a21f58Wu-cheng Li /// list. 172c5e37cbb96b8284203560c51dd5f41c705a21f58Wu-cheng Li SourceLocation RAngleLoc; 1739f73bd9a85d295091fae39dc256a122e1843e2e8Wu-cheng Li 174c5e37cbb96b8284203560c51dd5f41c705a21f58Wu-cheng Li /// NumArgs - The number of template arguments. 175c5e37cbb96b8284203560c51dd5f41c705a21f58Wu-cheng Li unsigned NumArgs; 1768ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li 1778ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li /// \brief Retrieves a pointer to the template arguments 1788ab2b624d51b3b8254ece98c46a7e22a6fb5d4aaWu-cheng Li ParsedTemplateArgument *getTemplateArgs() { 1793f63a2d895c50ae1c3a7a47ee6ead070b5bbd7fcWu-cheng Li return reinterpret_cast<ParsedTemplateArgument *>(this + 1); 1803f63a2d895c50ae1c3a7a47ee6ead070b5bbd7fcWu-cheng Li } 1813f63a2d895c50ae1c3a7a47ee6ead070b5bbd7fcWu-cheng Li 1823f63a2d895c50ae1c3a7a47ee6ead070b5bbd7fcWu-cheng Li static TemplateIdAnnotation* Allocate(unsigned NumArgs) { 183b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project TemplateIdAnnotation *TemplateId 184c30e5c21c3858c15473427d82608c473d44bf3e4Chih-Chung Chang = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) + 185cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang sizeof(ParsedTemplateArgument) * NumArgs); 186cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang TemplateId->NumArgs = NumArgs; 187cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang 188f63366e6305e75ae289aaac20b397a3e9633d9dfHung-ying Tyan // Default-construct nested-name-specifier. 189f63366e6305e75ae289aaac20b397a3e9633d9dfHung-ying Tyan new (&TemplateId->SS) CXXScopeSpec(); 190f63366e6305e75ae289aaac20b397a3e9633d9dfHung-ying Tyan 191f63366e6305e75ae289aaac20b397a3e9633d9dfHung-ying Tyan // Default-construct parsed template arguments. 192a5c1d8bf69892292d7efee102503b9d851fbf834Wu-cheng Li ParsedTemplateArgument *TemplateArgs = TemplateId->getTemplateArgs(); 19359ddc8c1add2fcffe523e3877baad1b6cc5ba2fbChung-yih Wang for (unsigned I = 0; I != NumArgs; ++I) 19459ddc8c1add2fcffe523e3877baad1b6cc5ba2fbChung-yih Wang new (TemplateArgs + I) ParsedTemplateArgument(); 1956490868a51c9b8c79f30c8d257f89adb8d26b7b9Owen Lin 1966490868a51c9b8c79f30c8d257f89adb8d26b7b9Owen Lin return TemplateId; 1976490868a51c9b8c79f30c8d257f89adb8d26b7b9Owen Lin } 1986490868a51c9b8c79f30c8d257f89adb8d26b7b9Owen Lin 1996490868a51c9b8c79f30c8d257f89adb8d26b7b9Owen Lin void Destroy() { 2006490868a51c9b8c79f30c8d257f89adb8d26b7b9Owen Lin SS.~CXXScopeSpec(); 2016490868a51c9b8c79f30c8d257f89adb8d26b7b9Owen Lin free(this); 2026490868a51c9b8c79f30c8d257f89adb8d26b7b9Owen Lin } 2036490868a51c9b8c79f30c8d257f89adb8d26b7b9Owen Lin }; 20449bc3fd984521c8c8eed8733d9bdd7f2ccdd9057Wu-cheng Li 20549bc3fd984521c8c8eed8733d9bdd7f2ccdd9057Wu-cheng Li /// Retrieves the range of the given template parameter lists. 206855b4ca04f982c7110acd81b509c955df976926fWu-cheng Li SourceRange getTemplateParamsRange(TemplateParameterList const *const *Params, 20795fc5b2c5b14bb81332570f6d74f75cd63ea04b5Wu-cheng Li unsigned NumParams); 20895fc5b2c5b14bb81332570f6d74f75cd63ea04b5Wu-cheng Li 20995fc5b2c5b14bb81332570f6d74f75cd63ea04b5Wu-cheng Li inline const ParsedTemplateArgument & 21095fc5b2c5b14bb81332570f6d74f75cd63ea04b5Wu-cheng Li ASTTemplateArgsPtr::operator[](unsigned Arg) const { 211b64d345c9d51cabce43b5191532a0c185d2a70a5The Android Open Source Project return Args[Arg]; 21249bc3fd984521c8c8eed8733d9bdd7f2ccdd9057Wu-cheng Li } 21349bc3fd984521c8c8eed8733d9bdd7f2ccdd9057Wu-cheng Li} 21449bc3fd984521c8c8eed8733d9bdd7f2ccdd9057Wu-cheng Li 21549bc3fd984521c8c8eed8733d9bdd7f2ccdd9057Wu-cheng Li#endif 21649bc3fd984521c8c8eed8733d9bdd7f2ccdd9057Wu-cheng Li